对于独立客户端开发者来说,维护一个服务器成本相当高:你需要学习服务端技能、租用服务器、考虑扩展问题、还得花精力去维护,还有一个微不足道的原因是租服务器要花钱。
幸亏 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 ,可以很方便地进行数据的管理。