Baas
对于独立客户端开发者来说,维护一个服务器成本相当高:你需要学习服务端技能、租用服务器、考虑扩展问题、还得花精力去维护,还有一个微不足道的原因是租服务器要花钱。
幸亏 IT 巨头们已经帮我们解决了这个问题,把后端能力打包成一个服务,让开发者不需要操心服务器相关的任何事情,只需要直接调用 API,这就是传说中的 BaaS(Backend as a Service)。
典型的 BaaS 包含下面的功能:
- 数据存储
- Crash 统计
- Analytics
- 远程配置
- 推送
强大如 Firebase 还有其他许多功能:
- Dynamic Link(跨平台的 Universal Link)
- AdMob 广告平台
- Web 托管
实际上,如果你的 app 体量不大并且功能简单,可以不花钱享受上面的所有服务。但弊端是一旦体量大了,需要更多的服务端开发需求时,BaaS 就很难满足了。
平台选择
市面上已经有很多 BaaS 平台可选:
- Google 的 Firebase:功能全面且强大,但由于是 Google 的服务,被 GFW 照顾得很好。实测 Analytics 和 AdMob 功能可用(后台需要翻墙),数据库功能和动态链接功能被墙。
- LeanCloud:有存储、消息、分析功能,算国内名气比较大的 BaaS 提供商。
- WildDog:主要致力于通信领域,了解不多。
- CloudKit:苹果亲儿子,主要提供的是数据存储功能,可以在 iOS/macOS 和 Web 端访问。
选择 CloudKit 的原因一般有几个:
- Apple 自家的服务,基本不用担心服务稳定性和公司哪天突然倒闭的问题。
- 和 Apple ID 打通,如果不想搭建自己的账号系统,可以不用关心账户体系的问题。
- Apple 和某组织关系处理得比较好,不会被照顾。
缺点也很明显:不支持安卓。
功能
CloudKit 的主要功能是存储数据(CURD)和监听数据变化,后者可以方便地实现多端(Apple 全家桶)的数据同步。
基本概念
上面这张图出自 WWDC 2017 的 keynote,很好地展示了 CloudKit 中的核心概念。
- Apple 提供了两套数据库环境:Development 和 Production,两个环境功能相同但数据是隔离的,方便开发和测试。
- 每个数据环境中包含三个数据库:
- Public Database:任何人可读写。
- Shared Database:可以用来实现用户间的数据共享,比如便签的共享。
- Private Database:每个用户只能访问自己的数据,开发者无法访问。
- 数据库内部可以包含多个 Zone,一般使用默认的 Zone 就足够了。
- 每个 Zone 中包含若干的 Record,可以理解成数据中的一行,每条 Record 都有自己的 RecordType,用来描述每个字段的名称和类型。
- Reference:Record 中的字段可以引用其他的 Record 来表达关系。
下面有一张术语对照表:
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
方法即可。因为是网络调用,因此要做好错误处理。
1 | let publicDB = CKContainer.default().publicCloudDatabase |
查询数据
我们有两种方式查询数据:
- 通过 CKRecordID 获取一条数据
1 | let recordID = CKRecordID(recordName: "GreatPlace") |
- 通过 CKQuery 查询满足条件的多条数据
1 | let predicate = NSPredicate(format: "name BEGINSWITH 'Apple Store'") |
修改数据
查询数据,修改,然后保存。
删除数据
过程跟 fetch 类似:
1 | let recordID = CKRecordID(recordName: "GreatPlace") |
订阅
我们可以通过 CKRecordZoneSubscription
或者 CKQuerySubscription
来订阅数据的变化,这样当数据发生变化时设备会收到推送。
1 | let predicate = NSPredicate(format: "description CONTAINS 'party'") |
Apple 写了一篇详细的文档来演示如何在本地缓存 CloudKit 的数据。
后台
Apple 还提供了一个 Dashboard,可以很方便地进行数据的管理。