iOS项目iCloud及CloudKit Dashboard运用
night123
8年前
<p>CloudKit是苹果最新推出的基于iCloud的一个云端数据存储服务.其 主要由下面两部分组成:</p> <ul> <li> <p>一个仪表web页面,用于管理公开数据的记录类型.</p> </li> <li> <p>一组API接口,用于iCloud和设备之间的数据传递.</p> </li> </ul> <p><strong>一、首先在XCode上面打开关于iCloud功能</strong></p> <p>1:进入对应的项目Targets 中的Capabilities 选项卡,打开关于iCloud功能;如果勾选iCloud Documents或CloudKit会自动生成一个带iCloud.开头的Containers,要配置证书支持;CloudKit Dashboard则可以直接跳转到Web配置关于iCloud的内容;而关于Steps则是配置的步骤是否都成功;</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/35032c20a9190ac50e6286f250ff959b.png"></p> <p><strong>二、关于证书如何配置支持iCloud功能</strong></p> <p>1:进入苹果证书管理后台中的Identifiers里有个iCloud Containers菜单</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/16977b6f6b380c7be0b521a10debf2c0.png"></p> <p>因为实例中的Bundle Identifier的名字wjy.com.MobileProject;所以在这边创建一个iCloud.wjy.com.MobileProject的ID值;都是前面增加一个iCloud为开头;app的bundle id需要与iCloud容器相对应,iCloud容器名必须是唯一的,因为这是Cloudkit用来访问数据所使用的全局标识符。由于iCloud容器名包含bundle id,因此bundle id也必须是唯一的(这就是为何需要修改com.raywendrelich.BabiFud)。</p> <p>为了让entitlements起作用,需要在App的证书、标识符与配置文件中ID的部分列出app/bundle id。这意味着标识的证书使用了设置的team id与app id,从中可得到iCloud容器的id。若已经在一个可用的开发者账号中标识了的话Xcode会自动完成这一切。不巧的是,这有时是不同步的,需要更新ID-使用iCloud功能面板修改CloudKit容器ID。否则的话需要修改info.plist文件或BabiFud.entitlements文件来确保id values与所设置的bundle id一致。</p> <p>2:创建完上面的ID后,同样进行Identifiers里的App IDs,找到我们当前的App ID然后对它进行编辑</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/912222b3138bfb1b6f382fdbba3083ef.png"></p> <p>打开 iCloud的功能选择,并且选择 Include CloudKit support,这边这时会有一个警告出现,选择右边的 Edit进行编辑</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/d43ae1a51772e4736b00b0d908c5ae13.png"></p> <p>这时会有刚才创建好的那个 iCloud ID可以选择绑定;选择好以后外面的警告也会消除;然后生成对应的描述文件安装后, XCode上面的步骤报错也会消除;</p> <p><strong>三、设置iCloud的数据</strong></p> <p>1:要进入CloudKit Dashboard操作有两种方式,第一种如上面第一点所说可以直接点CloudKit Dashboard进入,另一种就是进入苹果账号后台也有一个相应的菜单;</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b62000ac18062976250a524f71ee085a.png"></p> <p>2:进入CloudKit Dashboard可以看到如下的页面</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/2182d4856953d80c6cef98f08180119f.png"></p> <p>2.1 SCHEMA :</p> <p>CloudKit容器的高级类:Record Types, Security Roles, 和Subscription Types,其中主要使用的是Record Types;</p> <p>一个Record Type用来定义一个单独的记录(可以理解为一个数据模型),相当于存储数据的模板,和数据库的表结构类似;</p> <p>2.2 PUBLIC DATA 和 PRIVATE DATA</p> <p>就是你保存数据的地方,开发者可以查看所有的共享数据,但是只能看到自己的私密数据,无法看到用户的私密数据;这里没有显示PRIBATE DATA,其结构和PUBLIC DATA是一样的;</p> <p>User Records 记录一些当前使用者的信息;</p> <p>Default Zone :这里可以查看数据的详细信息,也是后面主要使用的;</p> <p>2.3 ADMIN 主要是管理开发者团队权限的,这里不做过多介绍;</p> <p>3:切回Record Type选项,点击右边栏的左上角的 "+ ",新增一个模型:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/4fb92cc5ab70c10c3a212fa4abe49cb7.png"></p> <p>输入模型名称: 默认只有一个StringField的属性(这里暂且这么称呼吧),可以点击下面的Add Field... 新增属性列表;</p> <p>同样可以选择属性的类型,如下图:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/31e7ce14e6c7dc660054d31a1bde3662.png"></p> <p>设置完成后,点击右下角的 Save按钮即可保存!这样,一个模型就建立好了;存储类型的数据:</p> <p>1. NSData (single bytes)</p> <p>2. NSDate (date and time)</p> <p>3. NSNumber (both Int and Double)</p> <p>4. NSString (or String in Swift)</p> <p>5. NSArray (list)</p> <p>6. CKReference (used to create relationships between objects)</p> <p>7. CLLocation (location)</p> <p>8. CKAsset (file)</p> <p>5:回到Default Zone,中间蓝色区域的右上角的名称旁有个倒三角,这里可以选择使用(查询)哪个模型下的数据:</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/b4170876e251057055006dad04e9f76d.png"></p> <p>6:如果要存是图片字段记得选Asset类型</p> <p style="text-align: center;"><img src="https://simg.open-open.com/show/ec499cda9d3565f73755f4145846758b.png"></p> <p>注意: 1 Public Record , 1 Private Record,意思是 :使用模型 Note的有一条公共数据,一条隐私数据,由于我登陆的 iCloud账号和开发者账号不一样,相当于是用户账号,所以这里是看不到那个隐私数据的</p> <p><strong>四、代码操作iCloud功能</strong></p> <p>1:首先引入CloudKit.framework系统框架,并引入命名空间#import 就可以进行操作</p> <p>2:首先是判断手机中的iCloud功能是否开启,如下面如果有值则表示已经开启的iCloud功能;</p> <pre> <code class="language-objectivec">id cloudUrl=[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];</code></pre> <p>这个方法接受一个参数, 就是要获取的容器标识。 所谓容器标识, 大多数应用只会用到一个 iCloud 容器,所以我们这里传入 nil, 就代表默认获取第一个可用的容器。这个方法内部会查找当前应用拥有的 iCloud 容器, 如果找到就会返回这个容器的 URL, 证明当前应用的 iCloud 容器可用。 如果找不到,就会返回 nil, 证明当前应用的 iCloud 不可用。</p> <p>注意: iCloud 容器和你 App 文件沙盒, 在 iOS 文件系统中其实是分别存放在两个不同的地方的:</p> <p>iCloud 文件路径格式 file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~xxx~aaa/Documents</p> <p>App 沙盒文件路径格式 file:///var/mobile/Containers/Data/Application/3B4376B3-89B5-3342-8057-3450D4224518/Documents/</p> <p>由此可见, 这也是为什么 iCloud 和 Sandbox 文件路径访问需要两套不同的方式的原因了。</p> <p>3:增加一条记录,可以给它一个固定的recordID,就像数据表的主键一样,查找、更新跟删除有用;</p> <pre> <code class="language-objectivec">-(void)addCloudDataWithPublic:(BOOL)isPublic recordID:(NSString *)recordID name:(NSString *)name password:(NSString *)password { //CloudKit给应用程序分配部分空间,用于存储数据,首先要获取这个存储空间,这里我们直接获取了默认的存储器(可以自定义存储器): CKContainer *container=[CKContainer defaultContainer]; CKDatabase *database; if (isPublic) { database=container.publicCloudDatabase; //公共数据 } else { database=container.privateCloudDatabase;//隐藏数据 } //创建主键ID 这个ID可以到时查找有用到 CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID]; //创建CKRecord 保存数据 CKRecord *noteRecord = [[CKRecord alloc]initWithRecordType:@"User" recordID:noteId]; //设置数据 [noteRecord setObject:name forKey:@"name"]; [noteRecord setObject:password forKey:@"password"]; //保存操作 [database saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) { if (!error) { [self showAlertMessage:@"保存成功"]; } }]; }</code></pre> <p>4 :假如要保存带有图片的字段,需要用到 CKAsset ,他的初始化需要一个 URL ,所以这里,我先把图片数据保存到本地沙盒,生成一个 URL ,然后再去创建 CKAsset:</p> <pre> <code class="language-objectivec">//增加带图片的提交 图片的保存,需要用到CKAsset,他的初始化需要一个URL,所以这里,我先把图片数据保存到本地沙盒,生成一个URL,然后再去创建CKAsset: -(void)saveImageDataWithPublic:(BOOL)isPublic recordID:(NSString *)recordID name:(NSString *)name password:(NSString *)password { //保存图片 图片的保存,需要用到CKAsset,他的初始化需要一个URL,所以这里,我先把图片数据保存到本地沙盒,生成一个URL,然后再去创建CKAsset: UIImage *image=[UIImage imageNamed:@"icloudImage"]; NSData *imageData = UIImagePNGRepresentation(image); if (imageData == nil) { imageData = UIImageJPEGRepresentation(image, 0.6); } NSString *tempPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/imagesTemp"]; NSFileManager *manager = [NSFileManager defaultManager]; if (![manager fileExistsAtPath:tempPath]) { [manager createDirectoryAtPath:tempPath withIntermediateDirectories:YES attributes:nil error:nil]; } NSString *filePath = [NSString stringWithFormat:@"%@/%@",tempPath,@"iCloudImage"]; NSURL *url = [NSURL fileURLWithPath:filePath]; [imageData writeToURL:url atomically:YES]; CKAsset *asset = [[CKAsset alloc]initWithFileURL:url]; //与iCloud进行交互 CKContainer *container=[CKContainer defaultContainer]; CKDatabase *database; if (isPublic) { database=container.publicCloudDatabase; //公共数据 } else { database=container.privateCloudDatabase;//隐藏数据 } //创建主键ID 这个ID可以到时查找有用到 CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID]; //创建CKRecord 保存数据 CKRecord *noteRecord = [[CKRecord alloc]initWithRecordType:@"User" recordID:noteId]; //设置数据 [noteRecord setObject:name forKey:@"name"]; [noteRecord setObject:password forKey:@"password"]; [noteRecord setObject:asset forKey:@"userImage"]; //保存操作 [database saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) { if (!error) { [self showAlertMessage:@"保存成功"]; } }]; }</code></pre> <p>其它修改、查找、删除的代码可以直接见下面的源代码地址;</p> <p><strong>五、操作实例</strong></p> <p>编写一个关于在同一台手机上免登录的实例,主要原理是通过获取手机设备唯一码,然后通过iCloud保存到云端,在删除APP后再安装后就可以直接从云端获得用户跟密码;会不断完善此实例,如果感兴趣可以点星并关注,会接着编写关于iCloud关于文件的同步功能;注意证书可以换成自个的,步骤如上:</p> <p> </p> <p> </p> <p>来自:http://www.cocoachina.com/ios/20161026/17786.html</p> <p> </p>