- 参考:http://blog.csdn.net/bawangxx/article/details/47999839
- https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/CloudKitQuickStart/Introduction/Introduction.html#//apple_ref/doc/uid/TP40014987-CH1-SW1
CloudKit使用教程<一>
CloudKit使用教程<二>
CloudKit是什么
- 我的理解就是云端数据库,存储数据,提供简单的增删改查功能
- 特点是方便简单,适合不懂后台的个人开发者.
- 安全,毕竟是苹果自家的产品.不需要复杂的登录认证体系.
- 国内也有类似的服务,免费版有一定限制,如优先级,请求数量,数据大小,及时性等.而目前苹果允许你使用 CloudKit 存储 10 GB 资源,100 M 数据库存储,每天 2 GB 流量;当你的用户数量增加的时候,这些免费额度也相应地增加到 1 PB 存储、10 TB 数据库存储,以及每天 200 TB 流量,几乎用不完.你感觉不够用的时候,你的用户量已经很庞大了....
集成
- 设置好bundleID 和 team
- 导入CloudKit框架
-
在 XCode 中的 Capabilities 选项卡中找到 iCloud 选项,并打开开关:
- 如果报错可以直接点击fix修复就可以了.或者在开发者中心配置appid(打开icloud,并手动添加容器),并且生成新的调试/发布证书,导入到本地.
-
这样就完成 CloudKit 的设置了。设置完成后,我们点击 CloudKit Dashboard 按钮,可以打开 CloudKit 管理后台:
-
关于共享容器,共享容器就是在同一个开发者不同app之间共享数据.在开发者中心 iCloud Containers这里添加新容器.
- 在上图选择sepcify custom containers,点击加好旁边的刷新按钮,就会出现新添加的容器.这个容器也可在其他app中被添加.
- 也可以直接点击加号添加新容器,系统会自动添加iCloud前缀
- 注意创建后的容器不能够删除,创建之前要想好,切记.
使用
支持的数据类型
增加一条记录
//创建索引ID
CKRecordID *artworkRecordID = [[CKRecordID alloc] initWithRecordName:@"115"];
//创建一条记录,type就是模型,与CloudKit 管理后台的Record types 一致,
//如果后台没有,会自动添加相应的模型或者字段.
CKRecord *artworkRecord = [[CKRecord alloc] initWithRecordType:@"Artwork" recordID:artworkRecordID];
//设置模型的数据,和字典用法几乎一样
artworkRecord[@"title" ] = @"MacKerricher State Park";
artworkRecord[@"artist"] = @"Mei Chen";
artworkRecord[@"address"] = @"Fort Bragg, CA";
//公有数据库,我建议写成宏
CKContainer *myContainer = [CKContainer defaultContainer];
CKDatabase *publicDatabase = [myContainer publicCloudDatabase];
//私有数据库
CKContainer *myContainer = [CKContainer defaultContainer];
CKDatabase *privateDatabase = [myContainer privateCloudDatabase];
//自定义的容器,比如上图中的共享容器,需要id标识
CKContainer *shareContainer = [CKContainer containerWithIdentifier:@"iCloud.com.example.ajohnson.GalleryShared"];
//添加一条记录(这里是添加到公有数据库里面)
[publicDatabase saveRecord:artworkRecord completionHandler:^(CKRecord *artworkRecord, NSError *error){
if (!error) {
//写入成功
}
else {
//写入失败的处理
}
}];
注意:
默认用户只能只读数据库,要添加修改则需要登录icloud账户
公有数据库所有的用户(安装app的用户,不是指开发者)都可以访问,私有的只能当前用户能访问.
如果用户没有登录,提醒用户登录icloud
[[CKContainer defaultContainer] accountStatusWithCompletionHandler:^(CKAccountStatus accountStatus, NSError* error) {
if (accountStatus == CKAccountStatusNoAccount) {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"尚未登录iCloud" message:nil preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定"
style:UIAlertActionStyleCancel
handler:nil]];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alert animated:YES completion:nil];
});
}
else {
//登录过了
}
}];
获取一条记录
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
CKRecordID *artworkRecordID = [[CKRecordID alloc] initWithRecordName:@"115"];
[publicDatabase fetchRecordWithID:artworkRecordID completionHandler:^(CKRecord *artworkRecord, NSError *error) {
if (error) {
//处理错误
}
else {
// 成功获取到数据
}
}];
修改记录
// 先获取记录
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
CKRecordID *artworkRecordID = [[CKRecordID alloc] initWithRecordName:@"115"];
[publicDatabase fetchRecordWithID:artworkRecordID completionHandler:^(CKRecord *artworkRecord, NSError *error) {
if (error) {
// 获取失败
}
else {
//修改记录
NSDate *date = artworkRecord[@"date"];
artworkRecord[@"date"] = [date dateByAddingTimeInterval:30.0 * 60.0];
//保存修改后的记录
[publicDatabase saveRecord:artworkRecord completionHandler:^(CKRecord *savedRecord, NSError *saveError) {
}];
}
}];
按照条件查询
- 查询title是
Santa Cruz Mountains
的记录
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"title = %@", @"Santa Cruz Mountains"];
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Artwork" predicate:predicate];
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
if (error) {
//处理错误
}
else {
// 查询成功
}
}];
-
查询条件如下:摘自官方文档
存储大文件(资源文件,如图片)
//本地文件的URL
NSURL *resourceURL = [NSURL fileURLWithPath:@"…"];
if (resourceURL){
CKAsset *asset = [[CKAsset alloc] initWithFileURL:resourceURL];
artworkRecord[@"image"] = asset;
//保存
}
添加地理位置
CLGeocoder *geocoder = [CLGeocoder new];
[geocoder geocodeAddressString:artwork[kArtworkAddressKey] completionHandler:^(NSArray *placemark, NSError *error){
if (!error) {
if (placemark.count > 0){
CLPlacemark *placement = placemark[0];
artworkRecord[kArtworkLocationKey] = placement.location;
}
}
else {
}
// 保存到数据库
}];
根据地理位置查询记录
//公有数据库
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
// 创建一个地理位置
CLLocation *fixedLocation = [[CLLocation alloc] initWithLatitude:37.7749300 longitude:-122.4194200];
//半径,单位是米
CGFloat radius = 100; // meters
//查找距离fixedLocation 不到100米的记录
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"distanceToLocation:fromLocation:(location, %@) < %f", fixedLocation, radius];
// 创建一个查询
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Artwork" predicate:predicate];
// 执行查询
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
if (error) {
//错误处理
}
else {
// 查询成功
}
}];
添加引用,类似于外键
- artist 引用了 artistRecordID这条记录
CKRecordID *artistRecordID = [[CKRecordID alloc] initWithRecordName:@"Mei Chen"];
CKReference *artistReference = [[CKReference alloc] initWithRecordID:artistRecordID action:CKReferenceActionNone];
CKRecord *artworkRecord;
…
artworkRecord[@"artist"] = artistReference;
查询引用
- 查询当前记录的引用
CKRecord *artworkRecord;
…
CKReference *referenceToArtist = artworkRecord[@"artist"];
//拿到引用的id
CKRecordID *artistRecordID = artistReference.recordID;
//根据id查询
[publicDatabase fetchRecordWithID:artistRecordID completionHandler:^(CKRecord *artistRecord, NSError *error) {
if (error) {
//错误处理
}
else {
// 查询成功
}
}];
- 查询artistRecordID的引用者(可以有很多个引用者)
NSPredicate *predicate = [NSPredicate predicateWithFormat:@“artist = %@”, artistRecordID];
//引用者类型为Artwork
CKQuery *query = [[CKQuery alloc] initWithRecordType:@“Artwork” predicate:predicate];
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
if (error) {
// 错误处理
}
else {
// 查询成功
}
}];
批处理操作
CKFetchRecordsOperation *fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs:fetchRecordIDs];
fetchRecordsOperation.perRecordCompletionBlock = ^(CKRecord *record, CKRecordID *recordID, NSError *error) {
if (error) {
}
else {
}
};
fetchRecordsOperation.fetchRecordsCompletionBlock = ^(NSDictionary *recordsByRecordID, NSError *error) {
if (error) {
}
else {
}
};
fetchRecordsOperation.database = [[CKContainer defaultContainer] publicCloudDatabase];
[fetchRecordsOperation start];
订阅 & 推送功能
CKRecordID *artistRecordID = [[CKRecordID alloc] initWithRecordName:@"Mei Chen"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"artist = %@", artistRecordID];
//创建一个订阅
CKSubscription *subscription = [[CKSubscription alloc]
initWithRecordType:@"Artwork"
predicate:predicate
options:CKSubscriptionOptionsFiresOnRecordCreation];
CKNotificationInfo *notificationInfo = [CKNotificationInfo new];
notificationInfo.alertLocalizationKey = @"New artwork by your favorite artist.";
notificationInfo.shouldBadge = YES;
subscription.notificationInfo = notificationInfo;
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
[publicDatabase saveSubscription:subscription
completionHandler:^(CKSubscription *subscription, NSError *error) {
if (error)
}
];
-
注册通知
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert categories:nil]; [application registerUserNotificationSettings:notificationSettings]; [application registerForRemoteNotifications];
-
处理通知
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { CKNotification *cloudKitNotification = [CKNotification notificationFromRemoteNotificationDictionary:userInfo]; NSString *alertBody = cloudKitNotification.alertBody; if (cloudKitNotification.notificationType == CKNotificationTypeQuery) { CKRecordID *recordID = [(CKQueryNotification *)cloudKitNotification recordID]; } }
然后在后台修改一条记录试试.