CK分享一步一步

共享CloudKit项目的指南

CKSharing是在WWDC 2016上引入的,它是他们的两个开发者演示的主要部分:CloudKit最佳实践和CloudKit的新功能。 通常,当有人说我需要在进行编码项目之前观看WWDC视频时,我通常会之以鼻,但这绝对是对的。 您确实必须观看这两个视频,才能对正在发生的事情有基本的了解。

而且,CloudKit 共享可能是我见过的Apple发布的Tentpole库中记录最少的主要功能。 写这篇文章几乎是公民的责任,这样其他人就不会像我所做的那样挣扎。 缺乏文档的原因之一是,我不认为CloudKit被开发人员经常使用。 与我交谈的大多数开发人员朋友都非常忙于使用JSON解析自定义后端,Firebase等…,以至于不介意最新和最出色的CloudKit产品是什么。 他们的损失!

该项目:

我从事应用程序开发已经有几年了(无论是打开还是关闭,大部分时间都是关闭的),可以帮助我追踪员工的工作时间。 这个概念很简单:有一个Manager ,他们有一个向他/她报告工作时间的Employee 。 允许员工自己添加,编辑,删除工时,并且经理在任何情况下都会收到通知。 然后,该应用将所有这些时间加起来,以便可以计算出工资单。 您可以想象,可以轻松地从这样的结构中构建其他功能,例如创建工资单,计算预扣税等。我们将只关注共享时间部分。

CloudKit结构:

由于一个经理可以有多个员工,因此我们在架构中需要一个Employee CKRecord类型。 它将包含名称,地址,工资率等…作为值。 这些小时将由我也在架构中创建的WorkEvent CKRecord表示。 每个WorkEvent都有一个startTime,endTime,注释等…以及对Employee的引用 现在我们只需要一个放置这些记录的地方。

公共数据库:在这里存储您希望每个人都可以访问的内容。 公共数据库中没有自定义区域,默认区域中所有内容都存在。

我们的数据(上述)显然是这两个方的私有数据,因此使用公共数据库是不可以的。 可以通过密钥共享来公开进行操作,但是基本上是通过模糊处理来实现安全性,这不理想。

私有数据库:您可以在其中存储不想让公众看到的记录 。 专用数据库具有默认区域,用户可以创建自定义区域。 重要提示 :将您要共享的任何内容放在私有数据库的自定义区域中。

对于此应用程序,管理中心将使用他/她的私有数据库来存储该应用程序的所有记录。 我们将为每个员工创建一个自定义区域,其中将有一个Employee CKRecord和许多WorkEvent CKRecords。 经理将订阅其私有数据库中的更改。

共享数据库:此数据库包含您已被授予访问权限的“对象的窗口”。 您在共享数据库中看到的记录存在于其他人的私有数据库中。 您只是有一个进入该对象的窗口 。 换句话说,您是共享数据库中项目的“贡献者”,而不是所有者。

对于此应用程序,员工将通过共享数据库访问其WorkEventsEmployee CKRecords。 他们将订阅共享数据库中的更改。 Manager的共享数据库中将没有任何区域,因为该信息位于其私有数据库中。 了解这一点非常重要。

注意:不要让术语“共享区域”绊倒您。 没有CKRecordZone这样的东西,您可以将记录放到与其他用户自动共享的地方。 共享区域只是为您创建的用于访问和添加共享记录的区域,但是它本身不会导致对象被共享,这将在以后进行介绍。

这将是什么样的:

CKShare对象

CKShare是一个CKRecord,它的作用就像一个从您的私有数据库到另一个用户的共享数据库的门户。 服务器将CKShare附加到CKRecord,您要做的就是创建CKShare并指出要将其附加到哪个记录。 您可以像其他任何CKRecord一样通过CKModifyRecordsOperation添加它。 添加CKShare对象时,它将在仪表板上创建一个记录类型,您可以检查该记录类型。 它甚至可以通过下拉菜单告诉您各种用户是谁,以及他们是否接受了邀请!

但是,在将CKShare记录添加到数据库之前,我们需要确定要与谁共享此数据。

让我们找人分享

有两种方法可以识别您想与谁共享的内容。 一种是“自定义”路由,另一种是UICloudSharingController路由。

自定义:我不会过多地讨论自定义路线,但是它涉及使用以下方法获取userDiscoverability的权限:

  CKContainer.default()。requestApplicationPermission(...) 

您需要包括您在请求.userDiscoverability,并设置一个completionHandler。 通过此方法, 其他用户可以看到您已经使用了此应用程序并被发现。 这将允许用户查找和操作CKUserIdentity对象,从而可以设置共享。 您可以通过这样做获得一些非常易于使用的体验,但是这需要大量的开发工作。 有一种更简单的方法…

UICloudSharingController:正如您从“ UI”部分可以看出的那样,这是呈现给用户的视图,可让他们选择想要与谁共享的对象。 在创建此视图时,还必须指出要共享的对象,以及创建CKShare对象。 让我们看一些代码。

  //注意:employeeRecord是我需要共享的CKRecord 
  let share = CKShare(rootRecord:employeeRecord) 
  share [CKShareTitleKey] =“某些标题”作为CKRecordValue?share [CKShareTypeKey] =“某些类型”作为CKRecordValue? 
 让sharedController = UICloudSharingController 
(preparationHandler:{(UICloudSharingController,处理程序:
@转义(CKShare ?, CKContainer ?, Error?)-> Void)在
 让modifyOp = CKModifyRecordsOperation(recordsToSave: 
[employeeRecord,共享],recordIDsToDelete:无)
  ModifyOp.modifyRecordsCompletionBlock = {(记录,recordID, 
错误)
处理程序(share,CKContainer.default(),错误)
}
  CKContainer.default()。privateCloudDatabase.add(modifyOp) 
  }) 
  SharingController.availablePermissions = [.allowReadWrite, 
.allowPrivate]
SharingController.delegate =自我
  self.present(sharingController,动画:true,完成:nil) 

首先,我们使用要共享的根记录创建一个CKShare对象。 在我们的实例中,我们将共享一个Employee记录(更多原因)

然后我们设置标题和类型键。 这些显示在您的仪表板中,希望我能告诉您这些功能是什么,但我还没有弄清楚它们的目的是什么🙂

然后,我们创建我们的UICloudSharingController,它以prepareHandler作为参数。 在prepareHandler中,您需要同时将共享记录和Employee记录添加到私有数据库中,以便可以共享它们。

然后,我们设置权限,例如,如果我们希望任何人都可以访问此Employee,或者仅是我们邀请的人。 然后,我们将委托设置为我们自己,并呈现sharedController。

瞧!

屏幕中间的名称是我要共享的对象的标题。 在这种情况下,我要共享“雇员”记录,所以我使用的是爱丽丝的名字,但是如果您要共享文档,则将是文档名,以此类推。…下面的电子邮件地址是您的iCloud电子邮件地址。 您可以通过委托方法将图像设置在屏幕中间,并将标题设置在屏幕中间。

  func cloudSharingController(_控制器:UICloudSharingController,failedToSaveShareWithError错误:错误){ 
//保存失败,比我处理错误要好:-)
//另外,此方法是必需的!
打印(错误)
}
  func itemThumbnailData(for:UICloudSharingController)->数据?  { 
//将图片设置在中间,默认为nil
您看到的文档图像,不需要此方法
返回零
}
  func itemTitle(for:UICloudSharingController)->字符串?  { 
//在此处设置标题,此方法是必需的!
//返回nil或未实现委托方法
结果为“无标题”
返回“爱丽丝·坎贝尔”
}
  //还有其他委托方法,请参阅文档。 

整个界面旨在帮助您将链接发送给其他用户。 链接是一个URL,当打开该URL时,它将在其他用户的设备上打开该应用程序,并在应用程序委托中调用一个名为userDidAcceptCloudKitShare的方法。 您需要在您的应用程序委托中实现此方法 ,否则该用户将无法接受分享。

  func application(_ application:UIApplication, 
userDidAcceptCloudKitShareWith cloudKitShareMetadata:
CKShareMetadata){

让acceptShareOperation:CKAcceptSharesOperation =
CKAcceptSharesOperation(shareMetadatas:
[cloudKitShareMetadata])

acceptShareOperation.qualityOfService = .userInteractive
acceptShareOperation.perShareCompletionBlock = {元,共享,
错误中
打印(“接受共享”)
}
  acceptShareOperation.acceptSharesCompletionBlock = { 
错误中
///将您的用户发送到他们需要进入您的应用程序的位置
}
  CKContainer(标识符: 
cloudKitShareMetadata.containerIdentifier).add
(接受共享操作)
}

TL; DR,我们在这里接受共享,我们有机会将用户放置在用户界面的正确位置以表示成功。

但是,我需要分享多个记录…

因此,如您所见,我们目前已完全共享一个记录。 如果您像我一样,可能会想知道您必须为要共享的每条记录执行此操作。 幸运的是,事实并非如此。

CKRecord现在具有一个名为Parent的属性。 我们使用parent来表示新的CKRecord与先前共享的记录相关。 在这种情况下,我们共享了Employee ,现在我们创建的所有WorkEvent都将共享的Employee CKRecord设置为其父项。 这将使所有“子级”工作事件在共享参与者的共享数据库中可见。 它们还受原始记录共享的共享条款的约束。

这就是为什么我前面提到我们会有一个Employee记录和几个WorkEvent记录的原因。 Employee记录是此操作的基础,我与某人共享该员工,然后他们可以访问所有将该Employee标记为其父级的WorkEvent 。 您可以根据需要选择任意数量的记录类型! (即收据,TaxProfile,Paycheck等)

因此,让我们创建一个孩子记录,以将其包含在原始共享中。

  //“ employeeRecord”是已与其他用户共享的CKRecord 
  //“事件”是我创建的coreData类,它等效于WorkEvent CKRecord,它包含需要设置为新CKRecord值的内容 
  //“区域”是我需要将此记录保存到的区域(包含该员工的所有记录的区域) 
 让newRecord = CKRecord(recordType:“ WorkEvent”,recordID:CKRecordID(recordName:event.recordName,zoneID:zone.zoneID)) 
  newRecord.setValue(event.hours,forKey:“小时”) 
newRecord.setValue(event.startTime,forKey:“ startTime”)
newRecord.setValue(event.endTime,forKey:“ endTime”)
newRecord.setValue(event.comments,forKey:“ comments”)
newRecord.setValue(event.type,forKey:“ type”)
 让参考= CKReference(记录:employeeRecord,操作:CKReferenceAction.deleteSelf) 
newRecord.setValue(reference,forKey:“ Employee”)
  newRecord.setParent(employeeRecord) 

是新WorkEvent的基本CKRecord构造函数。 您会注意到我正在根据用户输入(以我创建的CoreData类的形式)设置值。 我还创建了一个到Employee CKRecord的CKReference,因此我可以在CloudKit中获取删除规则。 最后,我设置了Parent属性,该属性允许与我共享Employee的其他用户访问我正在创建的新记录。

基本上就是这样

  • 自定义区域的 私有数据库中创建记录
  • 一旦知道与谁共享记录,便可以使用CKShare记录共享这些记录。
  • 共享数据库访问与您 共享的记录 ,但是请记住,这只是进入其他人的私有数据库的窗口。
  • 通过在新记录Parent属性下添加原始共享记录来共享其他记录
  • 订阅从其各自的数据库(即。 创建者通过其私有数据库进行 订阅 ,而贡献者通过共享数据库进行 订阅

如果这里有错误或不清楚的地方,请通过Twitter与我联系。

Interesting Posts