Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. CloudKit
Code

Xây dựng ứng dụng danh sách mua sắm cùng CloudKit: Bổ sung các mối quan hệ

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Building a Shopping List Application With CloudKit.
Building a Shopping List Application With CloudKit: Adding Records
Building a Shopping List Application With CloudKit: Sharing Shopping Items

Vietnamese (Tiếng Việt) translation by Thai An (you can also view the original English article)

Trong hướng dẫn trước của loạt bài này, chúng tôi đã bổ sung khả năng tạo mới, cập nhật và xóa danh sách mua sắm. Tuy nhiên, danh sách mua sắm không có bất kỳ mặt hàng nào trong đó không thực sự hữu ích. Trong hướng dẫn này, chúng tôi sẽ bổ sung khả năng tạo mới, cập nhật và xóa các sản phẩm khỏi danh sách mua sắm. Có nghĩa là chúng ta sẽ làm việc với các tham chiếu và class CKReference.

Chúng ta cũng sẽ tìm hiểu kỹ hơn mô hình dữ liệu của ứng dụng danh sách mua sắm. Thay đổi mô hình dữ liệu dễ thế nào và ứng dụng phản ứng với thế nào khi chúng ta thực hiện thay đổi trong CloudKit Dashboard (trang quản trị)?

Các điều kiện đầu tiên

Hãy nhớ tôi sẽ dùng Xcode 7Swift 2. Nếu bạn đang dùng một phiên bản Xcode cũ hơn, thì hãy nhớ rằng bạn đang dùng một phiên bản khác của ngôn ngữ Switf đấy.

Trong hướng dẫn này, chúng ta sẽ tiếp tục phần chúng ta còn dang dở trong phần hai của loạt bài này. Bạn có thể tải hoặc clone dự án từ GitHub.

1. Chi tiết danh sách mua sắm

Hiện tại người dùng có thể thay đổi tên của danh sách mua sắm bằng cách chạm vào dấu hiệu thông tin chi tiết, nhưng người dùng cũng có thể xem nội dung của một danh sách mua sắm bằng cách chạm vào một danh sách. Để thực hiện điều này, trước tiên ta cần một class con UIViewController.

Bước 1: Tạo ListViewController

Class ListViewController sẽ hiển thị nội dung của một danh sách mua hàng trong table view. Giao diện của class ListViewController tương tự với class ListsViewController. Chúng ta import các framework CloudKitSVProgressHUD và chiếu theo các protocol UITableViewDataSourceUITableViewDelegate. Bởi vì chúng ta sử dụng table view, chúng ta khai báo môt constant (hằng số), itemCell, sẽ hoạt động khi một cell tái sử dụng identifier (mã định danh).

Chúng ta khai báo 3 outlet, messageLabel thuộc kiểu UILabel!, tableView thuộc kiểu UITableView!, và activityIndicatorView thuộc kiểu UIActivityIndicatorView!. Controller của list view giữ một tham chiếu đến danh sách mua hàng mà nó đang hiển thị trong thuộc tính list, một kiểu CKRecord!. Các sản phẩm trong danh sách mua hàng được lưu trong thuộc tính items, cũng thuộc kiểu [CKRecord]. Cuối cùng, tôi dùng một biến helper, selection, để theo dõi sản phẩm nào trong danh sách mua sắm mà người dùng đã chọn. Điều này sẽ rõ ràng hơn ở phần sau trong hướng dẫn này.

Bước 2: Tạo giao diện người dùng

Mở Main.storyboard, bổ sung một view controller, và xét class của nó thành ListViewController trong Identity Inspector. Chọn prototype cell trong lists view controller, nhấn giữ phím control, và kéo prototype cell đến list view controller. Chọn Show từ trình đơn xổ xuống và xét identifier thành List trong Attributes Inspector.

Thêm một table view, một label, và một activity indicator view vào view của view controller.

Chọn table view và xét Prototype Cells thành 1 trong Attribute Inspector. Chọn prototype cell, xét Style thành Right Detail, Identifier thành ItemCell, và Accessory thành Disclosure Indicator. View controller sẽ trông thế này khi bạn hoàn tất:

List View Controller

Bước 3: cấu hình view controller

Trước khi chúng ta trở lại framework CloudKit, chúng ta cần chuẩn bị view controller cho dữ liệu sắp nhận. Bằng cách cập nhật triển khai cho viewDidLoad. Chúng ta xét tựa đề của view controller thành tên của danh sách mua sắm và gọi hai phương thức helper, setupViewfetchItems.

Phương thức setupView giống y như phương thức ta đã triển trong class ListsViewController.

Hãy tạo một phương thức quen thuộc khác, updateView. Trong updateView, chúng ta cập nhật giao diện người dùng của view controller dựa trên sản phẩm lưu trong thuộc tính items.

Tôi sẽ dể trống fetchItems lúc này. Chúng ta sẽ tiếp tục với phương thức này sau khi ta hoàn tất thiết lập list view controller.

Bước 4: Các phương thức Table View Data Source

Chúng ta gần như sẵn sàng để chạy một bài test khác cho ứng dụng. Trước khi làm việc này, chúng ta cần triển khai protocol UITableViewDataSource. Nếu bạn đã đọc các bài viết trước, thì phần triển khai sẽ tương tự.

Bước 5: Xử lý phần chọn lựa

Để kết nối mọi thứ cùng nhau, chúng ta cần trở lại class ListsViewController. Bắt đầu triển khai phương thức tableView(_:didSelectRowAtIndexPath:) của protocol UITableViewDelegate.

Ta cũng cần cập nhật prepareForSegue(segue:sender:) để xử lý cái chúng ta đã tạo ra trước đó. Có nghĩa là chúng ta cần thêm một case trong câu lệnh switch.

Để thuận tiên cho trình biên dịch, chúng ta cũng cần khai báo hằng số SegueList trên đầu file ListsViewController.swift.

Biên dịch và chạy ứng dụng để xem liệu mọi thứ đã kết hợp đúng chưa. Bởi vì chúng ta chưa triển khai phương thức fetchItems, nên không có sản phẩm nào hiển thị. Chúng ta cần thay đổi điều này.

2. Lấy các sản phẩm

Bước 1: Tạo kiểu cho bản ghi

Trước khi lấy sản phẩm từ backend của CloudKit, chúng ta cần tạo record type mới (kiểu bản ghi) trong CloudKit Dashboard. Đi đến CloudKit Dashboad, tạo một record type mới, đặt tên là items. Mỗi sản phẩm sẽ có tên, do đó hãy tạo một field mới, đổi tên field đó thành name và xét field type thành String.

Mỗi sản phẩm cũng sẽ thuộc về một danh sách mua sắm. Nghĩa là một sản phẩm cần một tham chiếu đến danh sách mua sắm của nó. Tạo một field mới, đổi tên thành list và xét field type là Reference. Kiểu Reference được thiết kế cho mục đích này, quản lý các mối quan hệ.

Item Record Type

Quay lại Xcode, mở ListsViewController.swift và khai báo một hằng số mới trên cùng của record type Items.

Bước 2: Lấy các sản phẩm

Mở ListViewController.swift và điều hướng đến phương thức fetchItems. Phần thực hiện tương tự phương thức fetchLists trong class ListsViewController. Dù vậy, có một khác biệt quan trọng.

Điểm khác biệt giữa fetchItemsfetchLists là thuộc tính ta đưa vào bộ khởi tạo CKQuery. Chúng ta không thích thú với những sản phẩm trong private database (cơ sở dữ liệu riêng tư) của người dùng. Chúng ta chỉ quan tâm đến sản phẩm có tương tác với một danh sách mua hàng cụ thể. Điều này thể hiện qua thuộc tính của đối tượng CKQuery.

Chúng ta tạo ra thuộc tính bằng cách truyền đến giá trị CKReference, chúng ta sẽ tạo ra bằng cách gọi init(recordID:action). Phương thức này nhận hai tham số, một đối tượng CKRecordID tham chiếu đến bản ghi danh sách mua sắm và đối tượng CKReferenceAction dùng để quyết định điều gì xảy ra khi danh sách mua hàng bị xoá bỏ.

Các hoạt động tham chiếu tương tự với các quy tắc xoá trong Core Data. Nếu đối tượng tham chiếu, tức danh sách mua hàng trong ví dụ này, bị xoá đi, thì framework CloudKit sẽ điều tra hoạt động tham chiếu để xác định điều gì sẽ xảy ra cho các bản ghi có tham chiếu đến bản ghi đã bị xoá. CKReferenceAction theo kiểu enum có 2 giá trị:

  • None: if tham chiếu đã bị xoá, thì bản ghi có tham chiếu đến bản ghị bị xoá không ảnh hưởng gì.
  • DeleteSelf: nếu tham chiếu bị xoá, mỗi bản ghi có tham chiếu đến bản ghi đã bị xoá cũng sẽ bị xoá.

Vì không có sản phẩm nào tồn tại mà kg thuộc về một danh sách mua hàng, chúng ta xét hành động của tham chiếu thành DeleteSelf.

Phương thức processResponseForQuery(records:error:) không có gì mới. Chúng ta xử lý phản hồi của câu truy vấn và cập nhật giao diện người dùng tương ứng.

Biên dịch và chạy ứng dụng. Bạn sẽ chưa thấy bất kỳ sản phẩm nào, nhưng giao diện người dùng sẽ cập nhật rằng danh sanh mua sắm đang rỗng.

3. Thêm mới sản phẩm

Bước 1: Tạo AddItemViewControler

Đây là lúc triển khai chức năng thêm mới các sản phẩm vào danh sách mua sắm. Băt đầu bằng việc tạo một class con của UIViewController, gọi là AddItemViewController. Giao diện của view controller tương tự với class AddListViewController.

Trên cùng, chúng ta import các framework CloudKitSVProgressHUD. Chúng ta khai báo protocol AddItemViewControllerDelegate, nó sẽ thực thi cùng mụch đích với protocol AddListViewControllerDelegate. Protocol này định nghĩa 2 phương thức, một để thêm mới sản phẩm, và một để cập nhật sản phẩm.

Chúng ta khai báo 2 outlet, một trường text (văn bản) và một bar button (nút bấm). Ta cũng khai báo một thuộc tính cho delegate và một biến helper newItem, biến này giúp ta xác định liệu chúng ta có tạo ra một sản phẩm mới không hay ta đang cập nhật một cái có sẵn. Sau cùng, ta khai báo thuộc tính list cho tham chiếu danh sách mua sắm đến sản phẩm sẽ được thêm vào và thuộc tính item cho sản phẩm chúng ta đang tạo ra hoặc đang cập nhật.

Trước khi tạo một giao diện người dùng, hãy triển khai 2 hành động mà ta sẽ cần trong kịch bản này, cancel(_:)save(_:). Chúng ta sẽ cập nhật phần triển khai cho hoạt động save(_:) ở phần sau của hướng dẫn.

Bước 2: tạo giao diện người dùng

Mở Main.storyboard, thêm một bar button vào thanh điều hướng của list view controller, và đổi System Item thành Add trong Attribute Inspector. Kéo một view controller từ Object Library và xét class của nó thành AddItemViewController. Tạo một seque từ mục bar button mà chúng ta vừa tạo ra để thêm item view controller. Chọn Show từ trình đơn xổ xuống và xét identifier của segue thành ItemDetail.

Thêm vào 2 bar button cho thanh điều hướng của add item view controller, một button cancel nằm bên trái và button save ở bên phải. Gắn kết hai bar button đó với hành động tương ứng của chúng. Thệm một field text (văn bản) vào view của view controller và đừng quên kết nối outlet của view controller. Khi bạn hoàn tất thì add item view controller sẽ giống thế này.

Add Item View Controller

Bước 3: Cấu hình View Controller

Phần triển khai của add item view controller không có gì mới mà chúng ta chưa đề cập qua. Trừ một ngoại lệ mà chúng ta sẽ thảo luận sau đây. Hãy bắt đầu cấu hình view controller trong viewDidLoad.

Chúng ta gọi setupView, một phương thức helper để cập nhật giá trị của newItem. Nếu thuộc tính item bằng nil, newItem sẽ là true. Điều này giúp ta xác định liệu ta có đang tạo ra hay cập nhật một danh sách mua sắm.

Chúng tôi cũng thêm view controller như một observer (quan sát viên) cho các thông bao của kiểu UITextFieldTextDidChangeNotification. Nghĩa là view controller được báo cáo khi nào nội dung của nameTextField có thay đổi.

Trong viewDidAppear(animated:), chúng ta hiển thị bàn phím bằng cách gọi becomeFirstReponder trong nameTextField.

Phương thức setupView gọi 2 phương thức helper: updateNameTextFieldupdateSaveButton. việc triển khai hai phương thức helper này rất rõ ràng. Trong updateNameTextField, chúng ta thêm dữ liệu vào trường text. Trong updateSaveButton, chúng ta bật hoặc tắt nút save tuỳ theo nội dung của trường text.

Trước khi chúng ta xem đến phần triển khai mới cập nhật của phương thức save(_:), ta cần triển khai phương thức textFieldDidChange(_:). Tất cả chúng ta cần làm là gọi updateSaveButton để bật hoặc tắt nút save.

Bước 4: Lưu các sản phẩm

Phương thức save(_:) thú vị nhất trong class AddItemViewController, vì nó chỉ cho ta làm sao để làm việc với các tham chiếu CloudKit. Hãy xem qua phần thực hiện của phương thức save(_:) dưới đây:

Hầu hết triển khai của nó tương tự nhau khi chúng ta đã nói việc lưu các bản ghi trong class AddListViewController. Điều làm chúng tôi thích thú là làm sao những sản phẩm duy trì tham chiếu đến danh sách mua sắm của nó. Đầu tiên chúng ta tạo một giá trị CKReference bằng cách gọi bộ khởi trị được chỉ định, init(recordID:action). Chúng ta đã nói qua chi tiết việc tạo một đối tượng CKReference khi ta tạo câu truy vấn để lấy sản phẩm của danh sách mua sắm.

Thông báo với sản phẩm về tham chiếu này rất dễ. Chúng ta gọi setObject(_:forKey:) trong thuộc tính item, truyền đối tượng CKReference vào làm giá trị và khoá là "list". Khoá này tương ứng với tên field chúng ta đã gán trong CloudKit Dashboard. Lưu sản phẩm vào iCloud giống hệt điều chúng ta đã thảo luận trước đây. Làm việc với các tham chiếu dễ dàng dễ đến vậy đó.

Phần triển khai của processResponse(record:error:) không có gì mới. Chúng ta kiểm tra xem liệu có lỗi nào hiện ra không, và nếy không có lỗi, ta thông báo cho delegate.

Bước 5: Cập nhật ListViewController

Chúng ta vẫn có vài việc cần làm trong class ListViewController. Bắt đầu bằng việc kết nối class ListViewController vào protocol AddItemViewControllerDelegate. Đây là thời điểm tốt để khai báo một hằng số cho segue với identifier là ItemDetail.

Phần triển khai của protocol AddItemViewControllerDelegate không đáng kể. Trong controller(_:didAddItem:), chúng tôi thêm sản phẩm vào items, sắp xếp items, tải lại table view, và gọi updateView.

Việc khai triển của controller(_:didUpdateItem:) thậm chí còn dễ hơn. Chúng ta sắp xếp items và tải lại table view.

Trong sortItems, chúng ta sắp xếp mảng của các giá trị CKRecord theo tên bằng hàm sortInPlace, một phương thức của protocol MutableCollectionType.

Có 2 tính năng khác ta cần thực hiện, cập nhật và xoá bỏ sản phẩm trong danh sách mua sắm.

Bước 6: Xoá sản phẩm

Để xoá sản phẩm, chúng ta cần triển khai tableView(_:commitEditingStyle:forRowAtIndexPath:) của protocol UITableViewDataSource. Chúng ta lấy sản phẩm cần xoá đi của danh sách mua sắm và truyến nó đến phương thức deleteRecord(_:).

Thực hành của deleteRecord(_:) không có gì mới. Ta gọi deleteRecordWithID(_:completionHandler:) trong private database và xử lý phần phản hồi trong completion handler.

Trong processResponseForDeleteRequest(record:recordID:error:) chúng ta cập nhật thuộc tính items và giao diện người dùng. Nếu có gì sai, chúng ta thông báo cho người dùng bằng cách dùng cảnh báo.

Bước 7: Cập nhật sản phẩm

Người dùng có thể cập nhật một sản phẩm bằng cách chạm vào chỉ báo xem chi tiết. Có nghĩa là chúng ta cần triển khai delegate method tên gọi tableView(_:accessoryButtonTappedForRowWithIndexPath:). Trong phương thức này, ta lưu chọn lựa của người dùng và tự thực hiện ListDetail segue. Lưu ý rằng không có gì xảy ra trong phương thức tableView(_:didSelectRowAtIndexPath:). Tất cả điều ta làm là bỏ chọn hàng mà người dùng đã chạm vào.

Trong prepareForSegue(_:sender:), chúng tôi lấy sản phẩm trong danh sách mua hàng bằng giá trị của thuộc tính selection và cấu hình destination view controller, một giá trị của class AddItemViewController.

Đó là tất cả điều ta cần làm để xoá và cập nhật sản phẩm trong danh sách mua hàng. Trong phần tiếp theo, chúng ta khám phá việc cập nhật data model (mô hình dữ liệu) trong CloudKit Dashboard dễ dàng đến thế nào.

4. Cập nhật Data Model (mô hình dữ liệu)

Nếu bạn từng làm việc với Core Data, thì bạn biết rằng việc cập nhật data model nên thực hiện cẩn trọng. Bạn cần chắc chắn không phá hỏng điều gì các lưu trữ nhất quán của ứng dụng. CloudKit thì linh hoạt hơn một chút.

Record type (kiểu bản ghi) items hiện giờ có 2 field, namelist. Tôi muốn cho bạn thấy điều gì tác động khi cập nhật data model thông qua việc thêm một field mới. Mở CloudKit Dashboard và thêm một field mới vào bản ghi Items. Xét tên field là number và xét field type thành Int(64). Đừng quên lưu thay đổi lại.

Update Item Record Type

Giờ bổ sung khả năng để điều chỉnh số lượng của item. Mở AddItemViewController.swift và khai báo 2 outlet, một label (nhãn) và một stepper.

Chúng ta cũng thêm một hành động cần được kích hoạt khi giá trị của stepper thay đổi. Trong numberDidChange(_:), chúng ta cập nhật nội dung của numberLabel.

Mở Main.storyboard và thêm một label và một stepper vào add item view controller. Kết nối outlet của view controller với thành phần giao diện người dùng tương ứng và kết nối hành động numberDidChange(_:) với stepper cho sự kiện Value Changed.

Update Add Item View Controller

Hành động save(_:) của class AddItemViewController cũng thay đổi chút ít. Hãy xem nó trông thế nào.

Ta chì cần thêm 2 dòng code. Trên cùng, chúng ta lưu giá trị của stepper trong một hằng số tên là number. Khi cấu hình item, chúng ta xét number như giá trị của khoá "number" và đó là tất cả gì phải làm.

Đồng thời ta cũng cần triển khai một phương thức helper để cập nhật giao diện người dùng của view controller để thêm sản phẩm. Phương thức updateNumberStepper kiểm tra liệu một bản ghi có field tên number hay không và nó có cập nhật stepper không nếu bản ghi đó có field này.

Chúng ta gọi updateNumberStepper trong phương thức setupView của class AddItemViewController.

Để hình dung con số của mỗi sản phẩm, chúng ta cần thực hiện một thay đổi đến ListViewController. Trong tableView(_:cellForRowAtIndexPath:), chúng ta xét nội dung của nhãn bên trái của cell thành giá trị của field tên number của sản phẩm.

Đó là tất cả điều cần làm để thực hiện thay đổi chúng ta áp dụng cho mô hình dữ liệu. Không cần phải thực hiện migration (chuyển dữ liệu) hoặc điều tương tự. CloudKit đảm nhận các chi tiết khó khăn rồi.

Tổng kết

Bây giờ bạn đã có một kiến thức cơ sở thích hợp của framework CloudKit. Hy vọng bạn đồng ý rằng Apple đã thành công khi tạo ra một framework và trang quản trị CloudKit. Còn nhiều thứ chúng ta chưa bàn đến trong loạt bài này, nhưng cũng đã đủ để bạn khởi đầu với CloudKit cho dự án của bạn.

Nếu có bất kỳ câu hỏi hay bình luận nào, bạn hãy thoải mái ghi lại ở phần bình luận hoặc kết nối với tôi trên Twitter.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.