iOS项目iCloud及CloudKit Dashboard运用
CloudKit是苹果推出的基于iCloud的一个云端数据存储服务.其 主要由下面两部分组成:
一个仪表web页面,用于管理公开数据的记录类型.
一组API接口,用于iCloud和设备之间的数据传递.
一:首先在XCode上面打开关于iCloud功能
1:进入对应的项目Targets 中的Capabilities 选项卡,打开关于iCloud功能;如果勾选iCloud Documents或CloudKit会自动生成一个带iCloud.开头的Containers,要配置证书支持;CloudKit Dashboard则可以直接跳转到Web配置关于iCloud的内容;而关于Steps则是配置的步骤是否都成功;
二:关于证书如何配置支持iCloud功能
1:进入苹果证书管理后台中的Identifiers里有个iCloud Containers菜单
因为实例中的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)。
为了让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一致。
2:创建完上面的ID后,同样进行Identifiers里的App IDs,找到我们当前的App ID然后对它进行编辑
打开iCloud的功能选择,并且选择Include CloudKit support,这边这时会有一个警告出现,选择右边的Edit进行编辑
这时会有刚才创建好的那个iCloud ID可以选择绑定;选择好以后外面的警告也会消除;然后生成对应的描述文件安装后,XCode上面的步骤报错也会消除;
三:设置iCloud的数据
1:要进入CloudKit Dashboard操作有两种方式,第一种如上面第一点所说可以直接点CloudKit Dashboard进入,另一种就是进入苹果账号后台也有一个相应的菜单;
2:进入CloudKit Dashboard可以看到如下的页面
2.1 SCHEMA :
CloudKit容器的高级类:Record Types, Security Roles, 和Subscription Types,其中主要使用的是Record Types;
一个Record Type用来定义一个单独的记录(可以理解为一个数据模型),相当于存储数据的模板,和数据库的表结构类似;
2.2 PUBLIC DATA 和 PRIVATE DATA
就是你保存数据的地方,开发者可以查看所有的共享数据,但是只能看到自己的私密数据,无法看到用户的私密数据;这里没有显示PRIBATE DATA,其结构和PUBLIC DATA是一样的;
User Records 记录一些当前使用者的信息;
Default Zone :这里可以查看数据的详细信息,也是后面主要使用的;
2.3 ADMIN 主要是管理开发者团队权限的,这里不做过多介绍;
3:切回Record Type选项,点击右边栏的左上角的 "+ ",新增一个模型:
输入模型名称: 默认只有一个StringField的属性(这里暂且这么称呼吧),可以点击下面的Add Field... 新增属性列表;
同样可以选择属性的类型,如下图:
设置完成后,点击右下角的 Save按钮即可保存!这样,一个模型就建立好了;存储类型的数据:
. NSData (single bytes)
. NSDate (date and time)
. NSNumber (both Int and Double)
. NSString (or String in Swift)
. NSArray (list)
. CKReference (used to create relationships between objects)
. CLLocation (location)
. CKAsset (file)
5:回到Default Zone,中间蓝色区域的右上角的名称旁有个倒三角,这里可以选择使用(查询)哪个模型下的数据:
6:如果要存是图片字段记得选Asset类型
注意:1 Public Record ,1 Private Record,意思是:使用模型Note的有一条公共数据,一条隐私数据,由于我登陆的iCloud账号和开发者账号不一样,相当于是用户账号,所以这里是看不到那个隐私数据的
四:代码操作iCloud功能
1:首先引入CloudKit.framework系统框架,并引入命名空间#import <CloudKit/CloudKit.h> 就可以进行操作
2:首先是判断手机中的iCloud功能是否开启,如下面如果有值则表示已经开启的iCloud功能;
id cloudUrl=[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
这个方法接受一个参数, 就是要获取的容器标识。 所谓容器标识, 大多数应用只会用到一个 iCloud 容器,所以我们这里传入 nil, 就代表默认获取第一个可用的容器。这个方法内部会查找当前应用拥有的 iCloud 容器, 如果找到就会返回这个容器的 URL, 证明当前应用的 iCloud 容器可用。 如果找不到,就会返回 nil, 证明当前应用的 iCloud 不可用。
注意: iCloud 容器和你 App 文件沙盒, 在 iOS 文件系统中其实是分别存放在两个不同的地方的:
iCloud 文件路径格式 file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~xxx~aaa/Documents
App 沙盒文件路径格式 file:///var/mobile/Containers/Data/Application/3B4376B3-89B5-3342-8057-3450D4224518/Documents/
由此可见, 这也是为什么 iCloud 和 Sandbox 文件路径访问需要两套不同的方式的原因了。
3:增加一条记录,可以给它一个固定的recordID,就像数据表的主键一样,查找、更新跟删除有用;
-(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:@"保存成功"];
}
}];
}
4:假如要保存带有图片的字段,需要用到CKAsset,他的初始化需要一个URL,所以这里,我先把图片数据保存到本地沙盒,生成一个URL,然后再去创建CKAsset:
//增加带图片的提交 图片的保存,需要用到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:@"保存成功"];
}
}];
}
5:查找单条记录的功能,通过recordID进行
//查找单条记录
-(void)searchRecordWithRecordID:(NSString *)recordID withFormPublic:(BOOL)isPublic
{
//获得指定的ID
CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID]; //获得容器
CKContainer *container=[CKContainer defaultContainer]; //获得数据的类型 是公有还是私有
CKDatabase *database;
if (isPublic) {
database=container.publicCloudDatabase;
}
else
{
database=container.privateCloudDatabase;
} __weak typeof(self)weakSelf = self;
//查找操作
[database fetchRecordWithID:noteId completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
NSString *message=[NSString stringWithFormat:@"获得RecordID为%@ 的数据:%@,%@",recordID,[record objectForKey:@"name"],[record objectForKey:@"password"]];
[weakSelf showAlertMessage:message];
}];
}
6:查询多条记录的功能,用到的谓词进行
//查找多条记录(可以用谓词进行)
-(void)searchRecordWithFormPublic:(BOOL)isPublic withRecordTypeName:(NSString *)recordTypeName
{
CKContainer *container=[CKContainer defaultContainer];
//获得数据的类型 是公有还是私有
CKDatabase *database;
if (isPublic) {
database=container.publicCloudDatabase;
}
else
{
database=container.privateCloudDatabase;
} NSPredicate *predicate=[NSPredicate predicateWithValue:YES];
CKQuery *query=[[CKQuery alloc]initWithRecordType:recordTypeName predicate:predicate]; __weak typeof(self)weakSelf = self;
[database performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {
[weakSelf showAlertMessage:[NSString stringWithFormat:@"%@",results]];
}];
}
7:更新一条记录首先要查找出该条记录,再对它进行修改,如果对应的键值存在进修改其值,如果键值不存在则增加新的类型字段;
//更新一条记录 首先要查找出这一条 然后再对它进行修改
-(void)updateRecordWithFormPublic:(BOOL)isPublic withRecordTypeName:(NSString *)recordTypeName withRecordID:(NSString *)recordID
{
//获得指定的ID
CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID]; //获得容器
CKContainer *container=[CKContainer defaultContainer]; //获得数据的类型 是公有还是私有
CKDatabase *database;
if (isPublic) {
database=container.publicCloudDatabase;
}
else
{
database=container.privateCloudDatabase;
} __weak typeof(self)weakSelf = self;
//查找操作
[database fetchRecordWithID:noteId completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
if (!error) { //对原有的健值进行修改
[record setObject:@"aa123456789" forKey:@"password"];
//如果健值不存在 则会增加一个
[record setObject:@"男" forKey:@"gender"]; [database saveRecord:record completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
if (!error) {
[weakSelf showAlertMessage:@"修改保存成功"];
}
else
{
[weakSelf showAlertMessage:[NSString stringWithFormat:@"出错误 :%@",error]];
}
}]; }
}];
}
8:删除一条记录
//删除记录
-(void)deleteRecordWithFormPublic:(BOOL)isPublic withRecordID:(NSString *)recordID
{
//获得指定的ID
CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID]; //获得容器
CKContainer *container=[CKContainer defaultContainer]; //获得数据的类型 是公有还是私有
CKDatabase *database;
if (isPublic) {
database=container.publicCloudDatabase;
}
else
{
database=container.privateCloudDatabase;
} __weak typeof(self)weakSelf = self;
[database deleteRecordWithID:noteId completionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
if (!error) {
[weakSelf showAlertMessage:@"删除成功"];
return;
}
[weakSelf showAlertMessage:[NSString stringWithFormat:@"删除失败 %@",error]];
}]; }
五:操作实例
编写一个关于在同一台手机上免登录的实例,主要原理是通过获取手机设备唯一码,然后通过iCloud保存到云端,在删除APP后再安装后就可以直接从云端获得用户跟密码;会不断完善此实例,如果感兴趣可以点星并关注,会接着编写关于iCloud关于文件的同步功能;注意证书可以换成自个的,步骤如上:
源代码地址:https://github.com/wujunyang/iCloudProject
最近有个妹子弄的一个关于扩大眼界跟内含的订阅号,每天都会更新一些深度内容,在这里如果你感兴趣也可以关注一下(嘿对美女跟知识感兴趣),当然可以关注后输入:github 会有我的微信号,如果有问题你也可以在那找到我;当然不感兴趣无视此信息;
iOS项目iCloud及CloudKit Dashboard运用的更多相关文章
- ios项目里扒出来的json文件
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...
- 上传IOS项目和版本更新流程图
上传IOS项目和版本更新流程图 必备IDP证书和distribution证书(第一个证书是真机部署测试时用到的,后者证书是发布时需要用到的,缺一不可). 我就说说接下来应该做的流程.在你保证拥有以上两 ...
- 开源 iOS 项目分类索引大全 - 待整理
开源 iOS 项目分类索引大全 GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Cate ...
- 现有iOS项目集成React Native过程记录
在<Mac系统下React Native环境搭建>配置了RN的开发环境,然后,本文记录在现有iOS项目集成React Native的过程,官方推荐使用Cocoapods,项目一开始也是使用 ...
- iOS项目的本地化处理(多国语言)
项目的本地化就是:iOS系统在不同语言环境下自动切换语言,从而实现一个app发布到全世界各个国家的AppStore上. 我们不仅仅需要在iOS项目中做本地化处理,在上架iOS APP的时候,也需要做对 ...
- 在Xcode 6 beta里编译Cocos2d-x iOS项目时失败
转载 在Xcode 6 beta里编译Cocos2d-x iOS项目时可能会失败,提示如下错误: Undefined symbols for architecture i386: "_fwr ...
- phonegap创建的ios项目推送消息出现闪退现象
使用phonegap创建的ios项目,推送消息时,当程序在前台运行或者在后台运行状态下,推送消息过来,可以解析并且跳转: 但是在程序从后台退出的状态下,当消息推送过来的时候,点击通知栏,打开程序,程序 ...
- MVVM 模式下iOS项目目录结构详细说明
➠更多技术干货请戳:听云博客 我们在做项目的时候,会经常用到各种设计模式,最常见的要数 MVC (模型,视图,控制器)了.但是,今天我们要说的是另一种设计模式——MVVM. 所以 MVVM 到底是什么 ...
- WinObjc - 使用iOS项目生成通用Windows应用
Github上一周年的WinObjc项目最近发布了预览版本,终于等到了这一天.WinObjc项目就是Build 2015大会上微软宣布的Project IslandWood项目,致力于将iOS应用快速 ...
随机推荐
- 工大助手(C#与python交互)
工大助手(爬虫--C#与python交互) 基本内容 工大助手(桌面版) 实现登陆.查成绩.计算加权平均分等功能 团队人员 13070046 孙宇辰 13070003 张帆 13070004 崔巍 1 ...
- 微软“.Net社区虚拟大会”dotnetConf2015:关键词:.NET 创新、开源、跨平台
去年 11 月的时候,微软开源了 .NET CoreFX,然后是今年 2 月份的 .NET CoreCLR.自那时以来,已经有大约 3500 人在 GitHub 上进行了提交,而且贡献者的人数还在持续 ...
- MyBatis2:config.xml文件
前言 前一篇文章,讲了MyBatis入门,讲到了MyBatis有两个基本的配置文件,一个用来配置环境信息,一个用来写SQL语句.前者我把它命名为config.xml,config.xml的内容是: & ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- ABP源码分析十八:UI Inputs
以下图中描述的接口和类都在Abp项目的Runtime/Validation, UI/Inputs目录下的.在当前版本的ABP(0.83)中这些接口和类并没有实际使用到.阅读代码时可以忽略,无需浪费时间 ...
- ABP框架 - 动态Web Api层
文档目录 本节内容: 创建动态Web Api控制器 ForAll 方法 重写 ForAll ForMethods Http 动词 WithVerb 方法 HTTP 特性 命名约定 Api 浏览器 Re ...
- 推荐一个不错的在线制图网站---ProcessOn
http://www.processon.com/ 它是什么? ProcessOn是一个面向垂直专业领域的作图工具和社交网络,成立于2011年6月并于2012年启动.ProcessOn将全球的专家顾问 ...
- 解析大型.NET ERP系统 多国语言实现
实现多国语言有许多种实现方案,无外乎是一种字符串替换技术,将界面控件的文本标签替换成相应语言的文字..NET Windows Forms实现多国语言的方法有以下几种: 1 .NET的方案,使用资源文件 ...
- GroupData群数据库的还原与优化
一.背景 这个数据库的数据文件mdf大概有83G左右,当还原数据库之后感觉可以做很多性能方面上的调优,合并数据后mdf数据文件大概有59G左右,行压缩后mdf数据文件大概有39G左右,页压缩后mdf数 ...
- windows 环境下nginx + tomcat群 + redis 实现session共享
nginx作为负载均衡根据定义将不同的用户请求分发到不同的服务器,同时也解决了因单点部署服务器故障导致的整个应用不能访问的问题 在加入nginx之后,如果多个服务器中的一个或多个(不是全部)发生故障, ...