对于独立客户端开发者来说,维护一个服务器成本相当高:你需要学习服务端技能、租用服务器、考虑扩展问题、还得花精力去维护,还有一个微不足道的原因是租服务器要花钱。
幸亏 IT 巨头们已经帮我们解决了这个问题,把后端能力打包成一个服务,让开发者不需要操心服务器相关的任何事情,只需要直接调用 API,这就是传说中的 BaaS(Backend as a Service)。
典型的 BaaS 包含下面的功能:
强大如 Firebase 还有其他许多功能:
实际上,如果你的 app 体量不大并且功能简单,可以不花钱享受上面的所有服务。但弊端是一旦体量大了,需要更多的服务端开发需求时,BaaS 就很难满足了。
市面上已经有很多 BaaS 平台可选:
选择 CloudKit 的原因一般有几个:
缺点也很明显:不支持安卓。
CloudKit 的主要功能是存储数据(CURD)和监听数据变化,后者可以方便地实现多端(Apple 全家桶)的数据同步。
上面这张图出自 WWDC 2017 的 keynote,很好地展示了 CloudKit 中的核心概念。
下面有一张术语对照表:
| RDBMS | LeanCloud | CloudKit |
|---|---|---|
| Database | Application | Database |
| Table | Class | Zone |
| Row | Object | Record |
| Index | Index | Index |
| JOIN | Reference | Reference |
了解了上面的概念后就可以开始使用了。首先需要在 Xcode 中开启 iCloud 中的 CloudKit 功能。
存储数据过程非常简单:获取一个 Public Database 的实例,创建一个 CKRecord,调用 saveRecord 方法即可。因为是网络调用,因此要做好错误处理。
let publicDB = CKContainer.default().publicCloudDatabase
let greatID = CKRecordID(recordName: "GreatPlace")
let place = CKRecord(recordType: "Place", recordID: greatID)
publicDB.save(place) { savedRecord, error in
// handle errors here
}
我们有两种方式查询数据:
let recordID = CKRecordID(recordName: "GreatPlace")
publicDB.fetch(withRecordID: recordID) { (fetchedPlace, error) in
guard let fetchedPlace = fetchedPlace else {
// handle errors here
return
}
let name = fetchedPlace["name"] as? String ?? "Unnamed Place"
fetchedPlace["name"] = name + " Door A" as CKRecordValue
}
let predicate = NSPredicate(format: "name BEGINSWITH 'Apple Store'")
let query = CKQuery(recordType: "Place", predicate: predicate)
publicDB.perform(query, inZoneWith: nil) { (results, error) in
// ...
}
查询数据,修改,然后保存。
过程跟 fetch 类似:
let recordID = CKRecordID(recordName: "GreatPlace")
publicDB.fetch(withRecordID: recordID) { (recordID, error) in
// handle errors here
}
我们可以通过 CKRecordZoneSubscription 或者 CKQuerySubscription 来订阅数据的变化,这样当数据发生变化时设备会收到推送。
let predicate = NSPredicate(format: "description CONTAINS 'party'")
let subscription = CKSubscription(recordType: "Checkin", predicate: predicate, options: .firesOnRecordCreation)
let info = CKNotificationInfo()
info.alertLocalizationKey = "NEW_PARTY_ALERT_KEY"
info.soundName = "NewAlert.aiff"
info.shouldBadge = true
subscription.notificationInfo = info
publicDB.save(subscription) { subscription, error in
//...
}
Apple 写了一篇详细的 文档 来演示如何在本地缓存 CloudKit 的数据。
Apple 还提供了一个 Dashboard ,可以很方便地进行数据的管理。