美文网首页iOS相关iOS开发
CloudKit使用教程<一>

CloudKit使用教程<一>

作者: youngyunxing | 来源:发表于2016-08-28 22:34 被阅读2169次

    CloudKit使用教程<一>
    CloudKit使用教程<二>

    CloudKit是什么

    • 我的理解就是云端数据库,存储数据,提供简单的增删改查功能
    • 特点是方便简单,适合不懂后台的个人开发者.
    • 安全,毕竟是苹果自家的产品.不需要复杂的登录认证体系.
    • 国内也有类似的服务,免费版有一定限制,如优先级,请求数量,数据大小,及时性等.而目前苹果允许你使用 CloudKit 存储 10 GB 资源,100 M 数据库存储,每天 2 GB 流量;当你的用户数量增加的时候,这些免费额度也相应地增加到 1 PB 存储、10 TB 数据库存储,以及每天 200 TB 流量,几乎用不完.你感觉不够用的时候,你的用户量已经很庞大了....

    集成

    • 设置好bundleID 和 team
    • 导入CloudKit框架
    • 在 XCode 中的 Capabilities 选项卡中找到 iCloud 选项,并打开开关:


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


      Paste_Image.png
    • 关于共享容器,共享容器就是在同一个开发者不同app之间共享数据.在开发者中心 iCloud Containers这里添加新容器.


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

    使用

    支持的数据类型

    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 {
            // 查询成功
        }
    }];
    
    
    • 查询条件如下:摘自官方文档


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

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

    Paste_Image.png

    相关文章

      网友评论

      • KyleBing:问个问题,我理解后台,但我不理解CloudKit到底是个什么玩意,我现在能存储,修改,删除数据了,但是还是不理解CloudKit 这个是给所有安装该应用的用户通用的吗?还是说只是给开发者自己用的?
        youngyunxing:@KyleBing 是的
        KyleBing:@iOSSinger 使用前需要有什么前提吗?也就是说用户在用app的时候,存储的数据都存储到我的 CloudKit里了是吗?那 Private 和 Public 是相对用户而言的喽?在 Private 里 一个用户存储的数据不会被另一个用户获取到,在 Public 下,用户的数据是共享的?
        youngyunxing:@KyleBing 给用户用的,存储用户的数据

      本文标题:CloudKit使用教程<一>

      本文链接:https://www.haomeiwen.com/subject/nmptettx.html