本文技术内容转自原帖
CloudKit牵扯了一系列的前期设置,详见参考
CloudKit 的基础对象类型有 7 种。这些对象类型可能和你在其他编程领域了解的类似对象类型稍有差别。
CKContainer
CKContainer
: Containers 就像应用运行的沙盒一样,一个应用只能访问自己沙盒中的内容而不能访问其他应用的。Containers 就是最外层容器,每个应用有且仅有一个属于自己的 container。事实上,经过开发者授权配置 CloudKit Dashboard
之后,一个应用也可以访问其他应用的 container。这里和App Group
相同,和iCloud Documents
也是一样的,允许不同App访问同一个存储空间。
属性和方法
+ (CKContainer *)defaultContainer; //默认容器
+ (CKContainer *)containerWithIdentifier:(NSString *)containerIdentifier; //根据identifier获取容器,同一个App有可能有多个iCloud容器。
- (void)addOperation:(CKOperation *)operation; //CKOperation 是CKDatabase操作的基类,继承他,重写main方法。
//私有云数据库
@property (nonatomic, readonly) CKDatabase *privateCloudDatabase;
//公有云数据库
@property (nonatomic, readonly) CKDatabase *publicCloudDatabase;
typedef NS_ENUM(NSInteger, CKAccountStatus) {
/* 无法获取账户*/
CKAccountStatusCouldNotDetermine = 0,
/* 账户可用 */
CKAccountStatusAvailable = 1,
/* 权限禁止使用 */
CKAccountStatusRestricted = 2,
/* 没有登陆iCloud账户 */
CKAccountStatusNoAccount = 3,
} NS_ENUM_AVAILABLE(10_10, 8_0);
//账户更换通知
CK_EXTERN NSString * const CKAccountChangedNotification NS_AVAILABLE(10_11, 9_0);
//获取账户状态,账户通过授权可以让知道你邮箱的人,知道你正在使用这个应用。
- (void)accountStatusWithCompletionHandler:(void (^)(CKAccountStatus accountStatus, NSError * __nullable error))completionHandler;
一个基本使用范例:
[[CKContainer defaultContainer] accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError * _Nullable error) {
void (^requestPremission)(void) = ^{
[[CKContainer defaultContainer] requestApplicationPermission:CKApplicationPermissionUserDiscoverability completionHandler:^(CKApplicationPermissionStatus applicationPermissionStatus, NSError * _Nullable error) {
switch (applicationPermissionStatus) {
case CKApplicationPermissionStatusCouldNotComplete:
{
//无法完成
NSLog(@"CKApplicationPermissionStatusCouldNotComplete");
break;
}
case CKApplicationPermissionStatusDenied:
{
//拒绝
NSLog(@"CKApplicationPermissionStatusDenied");
break;
}
case CKApplicationPermissionStatusGranted:
{
//授权通过
NSLog(@"CKApplicationPermissionStatusGranted");
break;
}
case CKApplicationPermissionStatusInitialState:
{
break;
}
default:
break;
}
}];
};
void (^signPremission)(void) = ^{
[[CKContainer defaultContainer] statusForApplicationPermission:CKApplicationPermissionUserDiscoverability completionHandler:^(CKApplicationPermissionStatus applicationPermissionStatus, NSError * _Nullable error) {
switch (applicationPermissionStatus) {
case CKApplicationPermissionStatusInitialState:
{
requestPremission();
break;
}
case CKApplicationPermissionStatusGranted:
{
//授权过了
break;
}
case CKApplicationPermissionStatusDenied:
{
//已经拒绝
break;
}
case CKApplicationPermissionStatusCouldNotComplete:
{
//无法获取状态
break;
}
default:
break;
}
}];
};
switch (accountStatus) {
case CKAccountStatusAvailable:
{
//账户可用
signPremission();
break;
}
case CKAccountStatusCouldNotDetermine:
{
//无法获取账户信息
break;
}
case CKAccountStatusNoAccount:
{
//当前无登录账户
break;
}
case CKAccountStatusRestricted:
{
//账户被禁用此功能
break;
}
default:
break;
}
}];
区别
CloudKit
和iCloud Documents
的区别在于,前者是存储在苹果服务器中的,后者则是存储在用户设备的特定区域中。
CKDatabase
CKDatabase
: Database 即数据库,私有数据库用来存储敏感信息,比如说用户的性别年龄等,用户只能访问自己的私有数据库。应用也有一个公开的数据库来存储公共信息,例如你在构建一个根据地理位置签到的应用,那么地理位置信息就应该存储在公共数据库里以便所有用户都能访问到。
CKRecord
CKRecord
: 即数据库中的一条数据记录。CloudKit 使用 record 通过 k/v 结构来存储结构化数据。关于键值存储,目前值的架构支持 NSString、NSNumber、NSData、NSDate、CLLocation,和 CKReference、CKAsset(这两个下面我们会说明),以及存储以上数据类型的数组。
增
CKRecord *postRecrod = [[CKRecord alloc] initWithRecordType:@"item"];
postRecrod[@"password"] = @"asdasdasdasd";
CKDatabase *publicDatabase = [[CKContainer defaultContainer] privateCloudDatabase];
[publicDatabase saveRecord:postRecrod completionHandler:^(CKRecord *record, NSError *error) {
if(error) {
NSLog(@"%@", error);
} else {
NSLog(@"Saved successfully");
}
}];
查
CKContainer *defaultContainer = [CKContainer defaultContainer];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
CKDatabase *publicDatabase = [defaultContainer privateCloudDatabase];
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"item" predicate:predicate];
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
if (!error) {
NSLog(@"%@", results);
} else {
NSLog(@"%@", error);
}
}];
改
CKContainer *defaultContainer = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [defaultContainer publicCloudDatabase];
CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:@"1"];
[publicDatabase fetchRecordWithID:recordID completionHandler:^(CKRecord *record, NSError *error) {
if(error) {
NSLog(@"%@", error);
} else {
record[@"postText"] = @"123 Beggers Canyon, Tatooine";;
[publicDatabase saveRecord:record completionHandler:^(CKRecord *record, NSError *error) {
if(error) {
NSLog(@"Uh oh, there was an error updating ... %@", error);
} else {
NSLog(@"Updated record successfully");
}
}];
}
}];
删
CKContainer *defaultContainer = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [defaultContainer publicCloudDatabase];
CKRecordID *recordID = [[CKRecordID alloc] initWithRecordName:@"1"];
[publicDatabase deleteRecordWithID:recordID completionHandler:^(CKRecordID *recordID, NSError *error) {
if(error) {
NSLog(@"%@", error);
} else {
NSLog(@"Deleted record successfully")
}
}];
特别注意,如果出现未知错误,请进入iCloud Dashboard调试
CKRecordZone
CKRecordZone
: Record 不是以零散的方式存在于 database 之中的,它们位于 record zones 里。每个应用都有一个 default record zone,你也可以有自定义的 record zone。
CKRecordIdentifier
CKRecordIdentifier
: 是一条 record 的唯一标识,用于确定该 record 在数据库中的唯一位置。
CKReference
CKReference
: Reference 很像 RDBMS 中的引用关系。还是以地理位置签到应用为例,每个地理位置可以包含很多用户在该位置的签到,那么位置与签到之间就形成了这样一种包含式的从属关系。
CKAsset
CKAsset
: 即资源文件,例如二进制文件。还是以签到应用为例,用户签到时可能还包含一张照片,那么这张照片就会以 asset 形式存储起来。