CloudKit使用教程<一>

  • 参考: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 选项,并打开开关:


    CloudKit使用教程<一>_第1张图片
    Paste_Image.png
  • 如果报错可以直接点击fix修复就可以了.或者在开发者中心配置appid(打开icloud,并手动添加容器),并且生成新的调试/发布证书,导入到本地.
  • 这样就完成 CloudKit 的设置了。设置完成后,我们点击 CloudKit Dashboard 按钮,可以打开 CloudKit 管理后台:


    CloudKit使用教程<一>_第2张图片
    Paste_Image.png
  • 关于共享容器,共享容器就是在同一个开发者不同app之间共享数据.在开发者中心 iCloud Containers这里添加新容器.


    CloudKit使用教程<一>_第3张图片
    Paste_Image.png
CloudKit使用教程<一>_第4张图片
Paste_Image.png
  • 在上图选择sepcify custom containers,点击加好旁边的刷新按钮,就会出现新添加的容器.这个容器也可在其他app中被添加.
  • 也可以直接点击加号添加新容器,系统会自动添加iCloud前缀
  • 注意创建后的容器不能够删除,创建之前要想好,切记.

使用

支持的数据类型

CloudKit使用教程<一>_第5张图片
Paste_Image.png

增加一条记录


    //创建索引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 {
        // 查询成功
    }
}];

  • 查询条件如下:摘自官方文档


    CloudKit使用教程<一>_第6张图片
    Paste_Image.png

存储大文件(资源文件,如图片)

   //本地文件的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];
      }
    }
    
    
  • 然后在后台修改一条记录试试.

别忘了最后一步,部署到线上.

CloudKit使用教程<一>_第7张图片
Paste_Image.png

你可能感兴趣的:(CloudKit使用教程<一>)