CloudKit实践

iOS,CloudKit

Posted by Karim on December 15, 2018

前言

在iOS 11后,有个接力的功能非常好用,可以在iPhone和Mac上共享剪贴板等。但是自己用的时候,总有很多小问题,明明需要打开的都打开了接力失效、上一次复制的是图片后来复制的是文本,iPhone直接剪贴板都不出来了。经历了一顿需求分析之后,决定自己动手做一个。
既然要实现跨平台,免不了要涉及到服务器,选择自己去写还是使用现有的云服务,成为了当前选择的最大问题。 为了解决又快又安全的问题,我最终选择了苹果自带的CloudKit

CloudKit

CloudKit是苹果在WWDC2014推出通过iCloud服务存储结构化应用程序和用户数据的框架,通过CloudKit获取app现有数据并将其存储在云中,实现用户多设备访问。

容器(Containers)

一个App可以创建和拥有多个容器:

//创建容器
let container = CKContainer(identifier: "在Capabilities选择的容器identifier")

一个容器中拥有PublicPrivateShared三种数据库,通过CKContainer的实例获取:

extension CKContainer {

    open var privateCloudDatabase: CKDatabase { get }

    open var publicCloudDatabase: CKDatabase { get }

    @available(OSX 10.12, *)
    open var sharedCloudDatabase: CKDatabase { get }
}

不同类型的数据库,可以通过下面的表格对比:

类型 占用用户iCloud容量 需要登录iCloud 访问
privateCloudDatabase 登录iCloud后允许访问,数据跟随iCloud账号
publicCloudDatabase 否,使用的是app的公共iCloud容量,具体参考这里 允许不登录iCloud账号,但只能读取,不能写入,同bundle id下所有用户都能访问
sharedCloudDatabase 所有app都可以访问

使用

在写代码之前,需要先去CloudKit dashboard,创建Record Type,同时在新建的Record Type页面新增字段,增加完字段之后,记得要为字段添加recordName索引,不然查询的时候会报错。

  1. 创建指定唯一记录名称的记录ID。
    let artworkRecordID = CKRecordIDrecordName:“115”)
    
  2. 创建一个记录对象。
    let artworkRecord = CKRecordrecordType:“Artwork”,recordIDartworkRecordID
    
  3. 设置记录的字段
    artworkRecord["title"] = "MacKerricher State Park"
    artworkRecord["artist"] = "Mei Chen"
    artworkRecord["address"] = "Fort Bragg, CA"
    
  4. 初始化容器并获取数据库对象
    let myContainer = CKContainer(identifier: "iCloud.com.example.ajohnson.GalleryShared") //如果使用默认容器,CKContainer.default()  
    let publicDatabase = myContainer.publicCloudDatabase
    
  5. 保存对象
    publicDatabase.save(artworkRecord) {
     (record, error) in
     guard let error = error else {
         // 处理错误
         return
     }
     // ...保存成功之后的处理
    }
    
  6. 查询
         let predicate = NSPredicate(value: true)
         let query = CKQuery(recordType: "Artwork", predicate: predicate)
         myContainer
         .publicCloudDatabase
         .perform(query, inZoneWith: nil, completionHandler: {
             (results, error) -> Void in
             OperationQueue.main.addOperation {
                     guard let error = error else {
                       // 处理错误
                     return
                     }
                     // ...保存成功之后的处理
             }
         })
    

应用

通过CloudKit,我分别在iOS上使用Today Widget,在Mac上监听键盘组合键来实现了接力中的共享粘贴板功能,目前功能还比较简单,不过基本也满足了我自己的需求了,后续有时间还是会完善一下复制图片、预览这些小功能的,代码在这里,感兴趣可以看一下。

参考链接

CloudKit官方文档
CKcontainer官方文档


请保持转载后文章内容的完整,以及文章出处。本人保留所有版权相关权利。

分享到: