Vietnamese (Tiếng Việt) translation by Vy Cam Nguyen (you can also view the original English article)
Trong hướng dẫn trước của loạt bài này, bạn đã bổ sung khả năng tạo mới, cập nhật và xóa danh sách mua sắm từ ứng dụng danh sách mua sắm trên nền iCloud. Trong hướng dẫn cuối cùng của loạt bài này, bạn sẽ sử dụng CKShare để chia sẻ một mục danh sách mua sắm cụ thể với người dùng khác.
Trong loạt bài này, bạn đã làm việc với các cơ sở dữ liệu private, cũng như đã tìm hiểu về cơ sở dữ liệu public. Tuy nhiên, khi Apple giới thiệu CKShare ở WWDC 2016, thì vẫn chưa có cách nào phù hợp để chia sẻ dữ liệu. Cơ sở dữ liệu private chỉ hỗ trợ cho những người dùng đã đăng nhập, trong khi cơ sở dữ liệu public được thiết kế cho nội dung public và cho phép bất cứ ai xem các bản ghi. Tuy nhiên, khi sử dụng một số ứng dụng iCloud do Apple sở hữu, chẳng hạn như Pages, Keynote hoặc Notes, bạn có thể nhận thấy bằng cách chọn nút chia sẻ, có khả năng mời người dùng khác truy cập dữ liệu của bạn.
Trong bài này, tôi sẽ trình bày cách chia sẻ nội dung một cách có chọn lọc.

Trong hướng dẫn này, bạn sẽ mang đến cho ứng dụng của mình khả năng tương tự, để người dùng có thể cộng tác với bạn trên một mục danh sách mua sắm được chia sẻ.
Điều kiện tiên quyết
Hãy nhớ rằng tôi sẽ dùng Xcode 9 và Swift 3. Nếu bạn đang sử dụng một phiên bản cũ của Xcode, hãy nhớ rằng bạn đang sử dụng một phiên bản khác của ngôn ngữ lập trình Swift.
Trong hướng dẫn này, chúng tôi tiếp tục phần ta đã xem trong hướng dẫn thứ ba của loạt bài. Bạn có thể download hoặc clone dự án từ GitHub.
Giới thiệu về cơ sở dữ liệu
Apple cung cấp ba loại cơ sở dữ liệu: public (công khai), private (riêng tư) và shared (được chia sẻ). Cơ sở dữ liệu public là nơi bạn tạo nội dung có sẵn mà mọi người đều có thể truy xuất, tất cả đều nằm trong vùng mặc định. Người dùng không cần trải qua xác thực với iCloud để xem nội dung nhưng họ không thể thay đổi.
Một cơ sở dữ liệu private bạn đã quen thuộc, vì ứng dụng mua sắm đã tận dụng cơ sở dữ liệu private để lưu trữ các bản ghi mà người khác không thể truy cập. Ngay bây giờ, tất cả danh sách mua sắm của bạn là danh sách riêng tư.
Cơ sở dữ liệu shared là cửa sổ cơ sở dữ liệu shared của Apple vào cơ sở dữ liệu private của bạn, cho phép người dùng truy xuất để đọc hoặc ghi dữ liệu qua CKShare.
Điều quan trọng cần lưu ý là cơ sở dữ liệu shared nằm trên tài khoản của người dùng được mời và là portal (cổng vào) cơ sở dữ liệu riêng của người sở hữu, với CKShare là một loại CKRecord cụ thể được kèm với CKRecord.

Bổ sung UICloudSharingController
Trước tiên, bạn sẽ triển khai UICloudSharingController và UICloudSharingControllerDelegate có liên quan của nó. Đến giờ cách dễ nhất để chia sẻ là sử dụng UICloudSharingController, nó sẽ chịu trách nhiệm cung cấp và trình bày những màn hình để chia sẻ bản ghi, mời người dùng và thiết lập quyền cho bản ghi của bạn, tất cả chỉ với một vài dòng code. Theo SDK của Apple, UICloudSharingController dễ dàng cho phép bạn:
- mời mọi người xem hoặc công tác trên bản ghi được chia sẻ
- thiết lập quyền để xác định ai có thể truy xuất bản ghi được chia sẻ (chỉ những người được mời hoặc bất kỳ ai có liên kết chia sẻ)
- thiết lập quyền chung hoặc cá nhân (chỉ đọc hoặc đọc/ghi)
- xóa quyền truy cập từ một hoặc nhiều người tham gia
- ngừng tham gia (nếu người dùng đã tham gia)
- ngừng chia sẻ với tất cả người tham gia (nếu người dùng là chủ sở hữu của bản ghi được chia sẻ)
Trong file ListViewController.swift của bạn, bao gồm đại biểu UICloudSharingControllerDelegate:
class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UICloudSharingControllerDelegate{
Tiếp theo, bổ sung phương thức didSelectRowAt: của TableView để khi người dùng chọn một ô, nó sẽ gọi bảng tính đang chia sẻ.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let item = items[indexPath.row] let share = CKShare(rootRecord: item) if let itemName = item.object(forKey: "name") as? String { self.itemName = item.object(forKey: "name") as? String share[CKShareTitleKey] = "Sharing \(itemName)" as CKRecordValue? } else { share[CKShareTitleKey] = "" as CKRecordValue? self.itemName = "item" } share[CKShareTypeKey] = "com.doronkatz.List" as CKRecordValue prepareToShare(share: share, record: item) }
Trong phương thức trên, bạn tạo CKShare, kết hợp mục CKRecord làm bản ghi gốc. Phương pháp sau đó đặt chia sẻ [CKShareTitleKey] và chia sẻ các thuộc tính [CKShareTypeKey] để chuẩn bị hiển thị bản ghi được chia sẻ. Phương thức cuối cùng gọi preparToShare, chuyển qua bản ghi gốc cũng như bản ghi được chia sẻ mới, mà bạn sẽ thực hiện tiếp theo:
private func prepareToShare(share: CKShare, record: CKRecord){ let sharingViewController = UICloudSharingController(preparationHandler: {(UICloudSharingController, handler: @escaping (CKShare?, CKContainer?, Error?) -> Void) in let modRecordsList = CKModifyRecordsOperation(recordsToSave: [record, share], recordIDsToDelete: nil) modRecordsList.modifyRecordsCompletionBlock = { (record, recordID, error) in handler(share, CKContainer.default(), error) } CKContainer.default().privateCloudDatabase.add(modRecordsList) }) sharingViewController.delegate = self sharingViewController.availablePermissions = [.allowReadWrite, .allowPrivate] self.navigationController?.present(sharingViewController, animated:true, completion:nil) }
Phương thức này tạo UICloudSharingController trong một trình xử lý block, bằng cách trước tiên lưu lại các bản ghi với CKModifyRecordsOperation vào cơ sở dữ liệu đám mây private của bạn, trước khi thông báo cho trình xử lý hoàn thành. Bạn cũng thiết lập các quyền hạn có sẵn của controller, trước khi hiển thị nó cho người dùng của bạn lúc sau cùng.
Triển khai các phương thức uỷ nhiệm UICloudSharingController
Bạn cũng cần triển khai hai phương thức ủy nhiệm bắt buộc, itemTitleForCloudSharingController và failedToSaveShareWithError. Có các phương thức ủy nhiệm tùy chọn khác mà bạn cũng có thể chọn để triển khai.
func cloudSharingControllerDidSaveShare(_ csc: UICloudSharingController) { print("saved successfully") } func cloudSharingController(_ csc: UICloudSharingController, failedToSaveShareWithError error: Error) { print("failed to save: \(error.localizedDescription)") } func itemThumbnailData(for csc: UICloudSharingController) -> Data? { return nil //You can set a hero image in your share sheet. Nil uses the default. } func itemTitle(for csc: UICloudSharingController) -> String? { return self.itemName }
Phương thức itemTitleForCloudSharingController phù hợp với thuộc tính CKShareTitleKey mà bạn đã thiết lập trước đó, yêu cầu tiêu đề hiển thị trong danh sách được mời. failedToSaveShareWithError thông báo cho đại biểu xử lý các yêu cầu chia sẻ không thành công. Hãy tiếp tục xây dựng và chạy ứng dụng của bạn, tạo một bản ghi, sau đó chọn một bản ghi riêng lẻ để kích hoạt bảng chia sẻ.

Nghe có vẻ tốt, nhưng việc của bạn vẫn chưa hoàn thành! Bạn cần xử lý làm thế nào những người dùng khác có thể nhận và hiển thị bản ghi được chia sẻ của bạn.
Nhận và xử lý các bản ghi CKShare
Cuối cùng, bạn cần thiết lập ứng dụng của mình để có thể tìm và hiển thị các bản ghi được chia sẻ. Mở file AppDelegate.swift của bạn và thêm phương thức ủy quyền userDidAcceptCloudKitShareWith:
func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) { let acceptSharing: CKAcceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata]) acceptSharing.qualityOfService = .userInteractive acceptSharing.perShareCompletionBlock = {meta, share, error in print(“successfully shared”) } acceptSharing.acceptSharesCompletionBlock = { error in guard (error == nil) else{ print(“Error \(error?.localizedDescription ?? “”)”) return } let viewController: AddItemViewController = self.window?.rootViewController as! AddItemViewController viewController.fetchShare(cloudKitShareMetadata) } CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptSharing) }
UserDidAcceptCloudKitShareWith: thông báo cho đại biểu rằng ứng dụng của bạn có quyền truy xuất vào thông tin được chia sẻ, giúp bạn có cơ hội xử lý nội dung mới. Nó thông báo cho bạn khi ứng dụng của bạn chia sẻ thành công một mục, cũng như các vấn đề trong quá trình chia sẻ, thông qua CKAcceptSharesOperation.
Trong phương thức này, bạn tạo một giá trị mới của AddItemViewController, gọi một hàm mới mà bạn tạo, fetchShare, cùng với metadata của sở thích. Phương pháp này cuối cùng đã bổ sung CKAcceptSharesOperation vào container của bạn. Để hiển thị bản ghi, hãy mở file AddItemViewController.swift và triển khai phương thức fetchShare:
func fetchShare(_ cloudKitShareMetadata: CKShareMetadata){ let op = CKFetchRecordsOperation( recordIDs: [cloudKitShareMetadata.rootRecordID]) op.perRecordCompletionBlock = { record, _, error in guard error == nil, record != nil else{ print(“error \(error?.localizedDescription ?? “”)”) return } DispatchQueue.main.async { self.item = record } } op.fetchRecordsCompletionBlock = { _, error in guard error != nil else{ print(“error \(error?.localizedDescription ?? “”)”) return } } CKContainer.default().sharedCloudDatabase.add(op) }
Trong phương thức cuối cùng này, bạn đang tìm bản ghi được chia sẻ và gán nó cho biến toàn cầu self.item, trước khi vẫn duy trì hoạt động trên cơ sở dữ liệu sharedDomainDatabase của người dùng của bạn.
Tổng kết
Trong hướng dẫn này, bạn đã học cách dễ dàng chỉ dùng vào dòng code để bổ sung khả năng chia sẻ một tập hợp con các bản ghi riêng tư của bạn với những người dùng khác và cùng họ hợp tác sử dụng những dữ liệu đó. Thông qua sức mạnh tuyệt đối và đơn giản của CKShare, bạn có thể chọn một mục danh sách mua sắm, mời người dùng truy xuất nó thông qua sheet UICloudSharingController và quản lý truy xuất và quyền của người dùng.
Ngoài việc chia sẻ bản ghi của bạn với người dùng, bạn cũng đã học cách nhận và hiển thị dữ liệu trong ứng dụng của họ, cũng như lưu trữ bản ghi trong cơ sở dữ liệu được chia sẻ của họ.
Như bạn có thể thấy, CloudKit cung cấp rất nhiều tiện lợi và mạnh mẽ, tất cả trong hệ sinh thái của Apple. Việc xác thực là hầu như không thể nhìn thấy được, không cần người dùng đăng nhập bằng email hoặc mật khẩu và việc đồng bộ dựa trên thời gian thực. Ngoài loạt bài này, tôi khuyến khích bạn khám phá các chủ đề nâng cao, chẳng hạn như đồng bộ hóa CloudKit với Core Data hoặc tạo logic lưu trữ của bạn để quản lý dữ liệu offline marshaling.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post