В предыдущем уроке этой серии вы добавили возможность создавать, обновлять и удалять списки покупок в своем приложении для покупок на основе iCloud. В последнем уроке этой серии вы будете использовать CKShare, чтобы делиться определенным элементом списка покупок с другим пользователем.
В этой серии вы работали с частными базами данных, а также изучали публичные базы данных. Однако до WWDC 2016 года, когда Apple представила CKShare , у приложений не было надлежащего способа обмена данными. Частные базы данных доступны только пользователям, вошедшим в систему, тогда как публичные базы данных предназначены для публичного контента и позволяют любому просматривать записи. Однако при использовании некоторых собственных приложений Apple iCloud, таких как Pages, Keynote или Notes, вы, возможно, заметили, нажав кнопку «Поделиться», — возможность пригласить других пользователей для доступа к вашим данным.
В этом посте я покажу вам, как делиться контентом.
В этом уроке вы предоставите вашему приложению те же возможности, чтобы пользователи могли совместно работать с вами в общем списке покупок.
Предпосылки
Помните, что я буду использовать Xcode 9 и Swift 3. Если вы используете более старую версию Xcode, имейте в виду, что вы используете другую версию языка программирования Swift.
В этом уроке мы продолжим с того места, на котором остановились в третьем уроке этой серии. Вы можете скачать или клонировать проект с GitHub .
О базах данных
Apple предоставляет три типа баз данных: публичные, частные и общие. Публичная база данных — это место, где вы делаете доступным контент, доступ к которому может получить каждый, и все в зоне по умолчанию. Пользователям даже не нужно проходить проверку подлинности с помощью iCloud для просмотра содержимого, но они не могут записывать изменения.
Частная база данных, с которой вы уже должны быть знакомы, поскольку приложение для покупок использует частную базу данных для хранения записей, к которым у общественности нет доступа. Прямо сейчас все ваши списки покупок являются частными списками.
Общая база данных — это окно общей базы данных Apple в вашу личную базу данных, которое предоставляет пользователям доступ для чтения или записи через CKShare
.
Важно отметить, что общая база данных находится в учетной записи приглашенного пользователя и является порталом для частной базы данных владельца, а CKShare
— это особый тип CKRecord
который присоединен к CKRecord
.
Добавление UICloudSharingController
Сначала вы реализуете UICloudSharingController
и связанный с ним UICloudSharingControllerDelegate
. Безусловно, самый простой подход к совместному использованию — это использование UICloudSharingController
, который заботится о предоставлении и представлении экранов для обмена вашей записью, приглашения пользователей и установки разрешений для вашей записи, и все это с помощью нескольких строк кода. Согласно SDK от Apple, UICloudSharingController
позволяет вам:
- приглашать людей для просмотра или совместной работы над общей записью
- установить права доступа, определяющие, кто может получить доступ к общей записи (только приглашенные пользователи или лица, имеющие ссылку на общий доступ)
- установить общие или индивидуальные разрешения (только чтение или чтение / запись)
- удалить доступ от одного или нескольких участников
- прекратить участие (если пользователь является участником)
- прекратить совместное использование со всеми участниками (если пользователь является владельцем общей записи)
В своем файле ListViewController.swift
UICloudSharingControllerDelegate
делегат UICloudSharingControllerDelegate
:
1
2
|
class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource,
UICloudSharingControllerDelegate{
|
Затем добавьте метод didSelectRowAt:
так, чтобы, когда пользователь выбирает ячейку, он вызывал лист совместного доступа.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
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?
self.itemName = item.object(forKey: «name») as?
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)
}
|
В приведенном выше методе вы создаете CKShare
, связывая item
CKRecord
в качестве корневой записи. Затем метод устанавливает свойства share[CKShareTitleKey]
и share[CKShareTypeKey]
при подготовке к отображению общей записи. Наконец, метод вызывает prepareToShare
, передавая исходную запись, а также только что созданную общую запись, которую вы будете реализовывать следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
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)
}
|
Этот метод создает UICloudSharingController
в обработчике блоков, сначала сохраняя записи с помощью CKModifyRecordsOperation
в вашей базе данных частного облака, прежде чем уведомлять обработчик завершения. Вы также устанавливаете доступные разрешения контроллера представления, прежде чем, наконец, представить его своему пользователю.
Реализация UICloudSharingController
делегата UICloudSharingController
Вам также необходимо реализовать два обязательных метода делегата, itemTitleForCloudSharingController
и failedToSaveShareWithError
. Есть и другие необязательные методы делегата, которые вы также можете выбрать для реализации.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
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.
}
func itemTitle(for csc: UICloudSharingController) -> String?
return self.itemName
}
|
Метод itemTitleForCloudSharingController
соответствует свойству CKShareTitleKey
вы установили ранее, запрашивая заголовок для отображения в списке приглашений. failedToSaveShareWithError
уведомляет делегата для обработки неудачных запросов на совместное использование. Соберите и запустите ваше приложение, создайте запись, а затем выберите отдельную запись, чтобы активировать лист обмена.
Это выглядит хорошо, но ваша работа еще не завершена! Вам необходимо определить, как другие пользователи могут получать и отображать вашу общую запись.
Получать и обрабатывать записи CKShare
Наконец, вам нужно настроить приложение, чтобы иметь возможность получать и отображать общие записи. Откройте файл AppDelegate.swift
и добавьте userDidAcceptCloudKitShareWith
делегата userDidAcceptCloudKitShareWith
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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!
viewController.fetchShare(cloudKitShareMetadata)
}
CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptSharing)
}
|
UserDidAcceptCloudKitShareWith:
уведомляет делегата о том, что ваше приложение имеет доступ к общей информации, давая вам возможность обрабатывать новый контент. Он уведомляет вас, когда ваше приложение успешно предоставило общий CKAcceptSharesOperation
к элементу, а также уведомляет вас о проблемах в процессе обмена, используя CKAcceptSharesOperation
.
В этом методе вы создаете новый экземпляр AddItemViewController
, вызывая новую fetchShare
вами функцию fetchShare
вместе с интересующими метаданными. Наконец, метод добавляет CKAcceptSharesOperation
в ваш контейнер. Чтобы отобразить запись, откройте файл AddItemViewController.swift
и fetchShare
метод fetchShare
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
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)
}
|
В этом последнем методе вы извлекаете общую запись и присваиваете ее своей глобальной переменной self.item
, прежде чем окончательно self.item
операцию в собственной sharedCloudDatabase
данных sharedCloudDatabase
вашего пользователя.
Вывод
Из этого учебного пособия вы узнали, как легко, всего за несколько строк кода, добавить возможность делиться подмножеством ваших личных записей с другими пользователями и взаимодействовать с ними на тех же данных. Благодаря простоте и простоте CKShare
, вы можете выбрать элемент списка покупок, пригласить пользователя получить доступ к вашему элементу через лист UICloudSharingController
и управлять доступом и разрешениями пользователя.
Помимо обмена своими записями с пользователями, вы также узнали, как получать и отображать данные в своих приложениях, а также сохранять записи в их общей базе данных.
Как вы можете видеть, CloudKit обеспечивает множество удобных и надежных функций в экосистеме Apple. Аутентификация практически невидима, при этом пользователям не требуется входить по электронной почте или паролю, а синхронизация выполняется в режиме реального времени. Помимо этой серии статей, я рекомендую вам изучить более сложные темы, такие как синхронизация CloudKit с Core Data или создание логики кэширования для управления автономным маршалингом данных.