服务器还是很有维护成本,对于小团队来说,不可能将各种。用AppStore进行分发,其实就是将销售方面交由Apple管理;换而言之,如果是用CloudKit进行开发,可以理解是将后端的也交由Apple管理。Apple为小团队们节省了很多不必要的开支。关于CloudKit网上有很多翻译苹果提供的最新文档,但是个人总感觉那些人并没有理解就进行翻译(Markdown程序员?),根本没有什么用。这篇文章是基于原版的英文文档,以及2014和2015年WWDC的视频整理而成的。
本篇文章不适合初心者,并不会升面试效果。
重要概念
整个数据库分成两个部分,public database和private database
- public算入开发者空间,private算入用户空间。
- 从大到小database->zone->record type->record->key-value
- User 的权限表属于record type 的一种
- public不能创建custom zones,只有private才能创建。 (注 Interacting with Record Zones)
- 可以进行订阅(subscription),监视两个数据库中的变化
- 定于分两个种,基于查询的订阅(query-based)和基于域的订阅(zone-based)
- 基于查询的订阅,当查询(query)条件为真的时候将会产生推送动作(取决于options)
- 基于域的订阅,将域(Zone)发生变化的时候将会产生推送动作(虽然method中有options这项,然而该参数并没有这种订阅的动作)
- 基于域的订阅只使用custom zone(注:找不到文档的明确说明,但是如果进行这样的操作就会收到 You can't create a subscription for the default zone的错误)
- 也就是说基于域的订阅只适用private database 的 custom zones
权限问题
- 关于一种Type的权限在 Record Type里设置
- 可以在Security Roles里面设置不同的角色
网上很多现有的方法是convenience method,主要是让大家快速的了解CloudKit,实际生产中应该使用NSOperation进行封装,在CloudKit里面就变成了CKOperation。
关于iCloud的使用流量和空间限制,是以“天”为计算周期的,Active User指的是日活,但是Asset的流量是按月重置。
记得引入CloudKit
import CloudKit
建立连接
首先连接Container
let container = CKContainer.defaultContainer() //连接默认的Container let container = CKContainer(identifier: "iCloud.me.masterchan.test0006") //连接特定的Container
然后选择是public还是private的database
let database = container.publicCloudDatabase let database = container.privateCloudDatabase
制作记录
使用CKRecord进行处理,个人理解,CKRecord有以下重要部分
- CKRecordID,在整个database唯一的,功能类似主键,可以通过这个来引索
- recordType,记录的类型,类似mysql的表结构
- key-value,键值对
- 还有修改的token,当然我们不应该去触碰这个结构,应该交由对象去处理
可以将CKRecordID设置成缺省值,这样系统将会自动为你生产一个唯一的ID
let record = CKRecord(recordType: "animate") let record = CKRecord(recordType: "animate", recordID: CKRecordID(recordName: "High School Fleet"))
接下来可以往里面放值,连Asset也可以往里面放
record["namech"] = "高校舰队" //可以用这种形式 record.setObject("ハイスクール・フリート", forKey: "namejp") //也可以用这种形式取决于代码样式 let dateComponents = NSDateComponents() dateComponents.day = 1 dateComponents.month = 4 dateComponents.year = 2016 let date = NSCalendar.currentCalendar().dateFromComponents(dateComponents)! record["begin"] = date//可以直接将日期放入其中 //let image = CKAsset(fileURL: NSURL(string: "https://img.rabbitcdn.com/common/9/9d/High_School_Fleet.jpg")!) //如果是Asset不能放远程的地址,能放就能做成DDoS了 let appRootPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] UIImagePNGRepresentation(UIImage(named: "High_School_Fleet")!)!.writeToFile(appRootPath.stringByAppendingString("/hfr.png"), atomically: true) let image = CKAsset(fileURL: NSURL(string: "file:" + appRootPath + "/hfr.png")!) //地址应该是file: 开头 record["picture"] = image
记录效果图
存储便捷方法
这些方法是让你快速入门的,因为这些都是涉及互联网的操作,会有一定延时,甚至可能会失败。所以正的操作中应该使用NSOperation(CKOperation)包装函数,并且感觉需要设置操作的优先级。
//保存数据 database.saveRecord(record) { (record, error) in print(error) } //根据ID读取数据 database.fetchRecordWithID(CKRecordID(recordName: "High School Fleet")) { (record, error) in if let jptitle = record?.objectForKey("namejp") as? NSString{ //downcast时可以用if和let嵌套 print(jptitle) } if let jptitle = record?.objectForKey("begin") as? NSString{ print(jptitle) }else{ print("error") } if let imgAsset = record?.objectForKey("picture") as? CKAsset{ dispatch_async(dispatch_get_main_queue(), { //注意操作需要回到主线程 self.kanImage.image = UIImage(data: NSData(contentsOfURL: imgAsset.fileURL)!) }) }else{ print("error") } }
下一篇文章将讲述一些更加深入读写方法,以及修改订阅的方法。