美文网首页iOS 开发学习
iOS开发-iCloud的简单使用(3)-Cloud Kit的使

iOS开发-iCloud的简单使用(3)-Cloud Kit的使

作者: 张囧瑞 | 来源:发表于2018-01-23 21:54 被阅读2613次

    好了,看完了key-value,看完了Document的存储,终于到了Cloud kit的使用了。

    比起前边的两种,Cloud kit更像是一个数据库。苹果会提供一个dashboard作为云存储的管理端。

    Cloud Kit 基础

    cloud kit一共有7个基础类,简单了解一下这些基础类接下来的使用就比较容易理解了。

    CKContainer

    CKContainer类似于应用运行时的沙盒,一个应用只能访问自己的沙盒,同样的,一个应用也只能访问自己的Container。

    通过初始化之后就可以使用

    
     CKContainer *container = [CKContainer defaultContainer];
    
    

    CKDatabase

    CKDatabase很明显就是数据库,他拥有私有数据库公有数据库两种类型。用户只能访问自己的私有数据库,一些不敏感的数据也可以存储在公有数据库中。

    
     //公有数据库
    
     CKDatabase *datebase = container.publicCloudDatabase;
    
     //私有数据库
    
     CKDatabase *datebase = container.privateCloudDatabase;
    
    

    CKRecord

    CKRecord就是数据库中的一条数据记录,他通过key-value的方式来存储和获取数据。目前可以支持如下格式的数据:

    • NSString(swift中的Sting)

    • NSNumber

    • NSData

    • NSDate

    • CLLocation

    • CKReference

    • CKAsset

    其中图片的数据类型需要先初始化一个URL,然后把图片保存到本地沙盒,生成URL,再创建CKAsset来存储。

    CKRecordZone

    CKRecordZone是用来保存Record的。所有的Record都是保存在这里,应用有一个默认的zone,也可以自定义zone

    CKRecordIdentifier

    CKRecordIdentifierRecord的唯一标示,用来确定Record在数据库中的位置。

    CKReference

    CKReference是一种引用关系。

    CKAsset

    CKAsset 为资源文件,比如之前提到的照片就是用这种方式存储的。

    CloudKit Dashboard

    更新:

    这里还有一个WWDC的视频介绍Cloud dashboard

    Build Better Apps with CloudKit Dashboard]

    CloudKit Dashboard 的入口在这里:

    CloudKitDashboardEnter.png

    你也可以直接访问地址

    这个界面好像更新过了,和网上很多教程的样式都不太一样。新的界面长这样:

    CloudKitDashboardWeb.png

    新的界面包括开发版和产品版(线上版)两种,在开发的时候我们就只针对左边的开发版进行操作就可以了。无论是那个版本,都有五个相同的入口。

    Data

    Cloud kit的数据管理中心入口。在这里可以进行数据的字段,索引等内容设定。

    Logs

    查看Cloud kit的服务日志,显示数据库操作,推送通知以及对应环境中的其他活动。

    Telemetry

    查看对应环境中服务器端性能和数据库利用率的图表。

    Public Database Usage

    查看公共数据库的使用情况图标,包括活跃用户、请求频率等。

    Api Access

    管理API令牌和服务器密钥,允许对应环境进行web服务调用。

    使用

    这次我们只讲简单的操作,所以本篇文章就只使用 Data中的部分功能。

    创建 RECORD TYPE

    首先点击Data , RECORD TYPE , Create New Type创建一个新的RECORD TYPE。

    CloudKitCreateRecordType.png

    这里注意,我们的RECORD TYPE Name 是Note,这个在之后代码里操作非常重要,所以记得不要写错了。

    添加 Field

    有了表,接下来就是添加字段了。点击Add Field 然后输入字段名,选择类型就可以了。这里可以一次性添加多条,添加完点击保存就可以了。

    CloudKitAddField.png

    添加的内容有:

    • title String

    • content String

    • photo Asset

    添加 indexs

    为了搜索更方便一些,我们添加一些索引。

    点击INDEXS,选择我们刚刚添加的Note,然后添加索引,添加的索引类型有QUERYABLE,SEARCHABLE,SORTABLE

    CloudKitAddIndex.png

    添加的内容有:

    • title QUERYABLE

    • title SEARCHABLE

    • title SORTABLE

    • content QUERYABLE

    • content SEARCHABLE

    • content SORTABLE

    • recordName QUERYABLE

    添加完就是这样的,对照一下看看有没有添加错啊。

    CloudKitAddIndexFinished.png

    添加数据

    接下来,我们就可以给表里添加数据了。

    选择RECORD ,确认LOAD RECORDS FROMQUERY FOR RECORDS OF TYPE 都正确了之后,点击Creat New Record...,在右边输入想要插入的数据,添加个几条就可以了。

    CloudKitAddRecord.png

    查询数据

    随便添加几条数据之后,还是在这个页面,点击左侧的Query Records,就可以查询到数据了。

    CloudKitQueryRecords.png

    到此,Cloud Dashboard的简单使用就介绍到这,接下来我们看看通过代码怎么来操作Cloud kit。

    撸起袖子写代码吧。

    通过代码操作 Cloud Kit

    使用Cloud Kit时,首先要先引入Cloud kit的框架。

    
    #import <CloudKit/CloudKit.h>
    
    

    添加数据

    首先创建一个容器

    
     //获取容器
    
     CKContainer *container = [CKContainer defaultContainer];
    
    

    然后获取数据库,这里我们使用公有数据库

    
     //公共数据
    
     CKDatabase *datebase = container.publicCloudDatabase;
    
    

    接下来创建一条数据,这里的RECORD_TYPE_NAME就是之前创建表的名字Note

    
     //创建保存数据
    
     CKRecord *noteRecord = [[CKRecord alloc] initWithRecordType:RECORD_TYPE_NAME];
    
    

    添加数据是使用Key-value的方式。

    
     [noteRecord setValue:title forKey:@"title"];
    
     [noteRecord setValue:content forKey:@"content"];
    
    

    这里要特殊注意的是图片的处理,我们先要创建一个URL,然后把图片数据保存到沙盒中,生成一个URL,再创建CKAsset。

    
     NSDate *dateID = [NSDate dateWithTimeIntervalSinceNow:0];
    
     NSTimeInterval timeInterval = [dateID timeIntervalSince1970] * 1000; //*1000表示到毫秒级,这样可以保证不会同时生成两个同样的id
    
     NSString *idString = [NSString stringWithFormat:@"%.0f", timeInterval];
    
     NSString *filePath = [NSString stringWithFormat:@"%@/%@",tempPath,idString];
    
     NSURL *url = [NSURL fileURLWithPath:filePath];
    
     [imageData writeToURL:url atomically:YES];
    
     CKAsset *asset = [[CKAsset alloc]initWithFileURL:url];
    
     [noteRecord setValue:asset forKey:@"photo"];
    
    

    对了,还有CKAsset转UIImage的方法:

    
    CKAsset *asset = [record objectForKey:@"photo"];
    
    UIImage *image = [UIImage imageWithContentsOfFile:asset.fileURL.path];
    
    

    这样数据的内容就处理好了,接下来我们只要把它保存起来就可以咯。

    
     [datebase saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
    
     if(!error)
    
     {
    
     NSLog(@"保存成功");
    
     }
    
     else
    
     {
    
     NSLog(@"保存失败");
    
     NSLog(@"%@",error.description);
    
     }
    
     }];
    
    

    整个代码合起来就是这样的:

    
    + (void)saveCloudKitModelWithTitle:(NSString *)title content:(NSString *)content photoImage:(UIImage *)image
    
    {
    
     //获取容器
    
     CKContainer *container = [CKContainer defaultContainer];
    
     //公共数据
    
     CKDatabase *datebase = container.publicCloudDatabase;
    
    // //私有数据
    
    // CKDatabase *datebase = container.privateCloudDatabase;
    
    // //创建主键
    
    // CKRecordID *noteID = [[CKRecordID alloc] initWithRecordName:@"NoteID"];
    
     //创建保存数据
    
     CKRecord *noteRecord = [[CKRecord alloc] initWithRecordType:RECORD_TYPE_NAME];
    
     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];
    
     }
    
     NSDate *dateID = [NSDate dateWithTimeIntervalSinceNow:0];
    
     NSTimeInterval timeInterval = [dateID timeIntervalSince1970] * 1000; //*1000表示到毫秒级,这样可以保证不会同时生成两个同样的id
    
     NSString *idString = [NSString stringWithFormat:@"%.0f", timeInterval];
    
     NSString *filePath = [NSString stringWithFormat:@"%@/%@",tempPath,idString];
    
     NSURL *url = [NSURL fileURLWithPath:filePath];
    
     [imageData writeToURL:url atomically:YES];
    
     CKAsset *asset = [[CKAsset alloc]initWithFileURL:url];
    
     [noteRecord setValue:title forKey:@"title"];
    
     [noteRecord setValue:content forKey:@"content"];
    
     [noteRecord setValue:asset forKey:@"photo"];
    
     [datebase saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
    
     if(!error)
    
     {
    
     NSLog(@"保存成功");
    
     }
    
     else
    
     {
    
     NSLog(@"保存失败");
    
     NSLog(@"%@",error.description);
    
     }
    
     }];
    
    }
    
    

    查询数据

    查询所有数据

    查询数据同样,我们也要先获取容器和数据库。

    
     //获取位置
    
     CKContainer *container = [CKContainer defaultContainer];
    
     CKDatabase *database = container.publicCloudDatabase;
    
    

    之后我们添加一个查询的条件,cloud kit和core data一样,都是使用NSPredicate

    而且还要用到CKQuery这个类。

    
     //添加查询条件
    
     NSPredicate *predicate = [NSPredicate predicateWithValue:YES];
    
     CKQuery *query = [[CKQuery alloc] initWithRecordType:RECORD_TYPE_NAME predicate:predicate];
    
    

    准备好了,接下来就可以调用查询方法了,获取到的results就是获取到数据的数组了,这里我用了通知的方法把查询到的数据传出去。

    
     //开始查询
    
     [database performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {
    
     NSLog(@"%@",results);
    
     //把数据做成字典通知出去
    
     NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:results forKey:@"key"];
    
     [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataQueryFinished" object:nil userInfo:userinfoDic];
    
     }];
    
    

    整个代码合起来就是这样的:

    
    //查询数据
    
    + (void)queryCloudKitData
    
    {
    
     //获取位置
    
     CKContainer *container = [CKContainer defaultContainer];
    
     CKDatabase *database = container.publicCloudDatabase;
    
     //添加查询条件
    
     NSPredicate *predicate = [NSPredicate predicateWithValue:YES];
    
     CKQuery *query = [[CKQuery alloc] initWithRecordType:RECORD_TYPE_NAME predicate:predicate];
    
     //开始查询
    
     [database performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {
    
     NSLog(@"%@",results);
    
     //把数据做成字典通知出去
    
     NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:results forKey:@"key"];
    
     [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataQueryFinished" object:nil userInfo:userinfoDic];
    
     }];
    
    }
    
    

    查询单个数据

    同样也是获取容器和数据库。

    
     //获取位置
    
     CKContainer *container = [CKContainer defaultContainer];
    
     CKDatabase *database = container.publicCloudDatabase;
    
    

    然后我们需要获取查询的数据的RecordID。

    
     [database fetchRecordWithID:recordID completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
    
     dispatch_async(dispatch_get_main_queue(), ^{
    
     NSLog(@"%@",record);
    
     //把数据做成字典通知出去
    
     NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:record forKey:@"key"];
    
     [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataSingleQueryFinished" object:nil userInfo:userinfoDic];
    
     });
    
     }];
    
    

    合起来代码就是这样的:

    
    //查询单条数据
    
    + (void)querySingleRecordWithRecordID:(CKRecordID *)recordID
    
    {
    
     //获取容器
    
     CKContainer *container = [CKContainer defaultContainer];
    
     //获取公有数据库
    
     CKDatabase *database = container.publicCloudDatabase;
    
     [database fetchRecordWithID:recordID completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
    
     dispatch_async(dispatch_get_main_queue(), ^{
    
     NSLog(@"%@",record);
    
     //把数据做成字典通知出去
    
     NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:record forKey:@"key"];
    
     [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataSingleQueryFinished" object:nil userInfo:userinfoDic];
    
     });
    
     }];
    
    }
    
    

    删除数据

    删除数据同样,我们也要先获取容器和数据库。

    
     //获取位置
    
     CKContainer *container = [CKContainer defaultContainer];
    
     CKDatabase *database = container.publicCloudDatabase;
    
    

    然后,在删除数据时,要获取到你要删除的数据的RecordID,之后直接执行删除方法即可

    
     [database deleteRecordWithID:recordID completionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
    
     if(error)
    
     {
    
     NSLog(@"删除失败");
    
     }
    
     else
    
     {
    
     NSLog(@"删除成功");
    
     }
    
     }];
    
    

    合起来代码就是这样

    
    //删除数据
    
    + (void)removeCloudKitDataWithRecordID:(CKRecordID *)recordID
    
    {
    
     CKContainer *container = [CKContainer defaultContainer];
    
     CKDatabase *database = container.publicCloudDatabase;
    
     [database deleteRecordWithID:recordID completionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
    
     if(error)
    
     {
    
     NSLog(@"删除失败");
    
     }
    
     else
    
     {
    
     NSLog(@"删除成功");
    
     }
    
     }];
    
    }
    
    

    修改数据

    还是那句话,先获取容器

    
     CKContainer *container = [CKContainer defaultContainer];
    
     CKDatabase *database = container.publicCloudDatabase;
    
    

    其实修改数据就是重新把数据写入。在写入的时候如果选择之前没有的key,就相当于新增了一个字段。然后执行保存操作就可以了。

    直接上全部的代码好了:

    
    //修改数据
    
    + (void)changeCloudKitWithTitle:(NSString *)title content:(NSString *)content photoImage:(UIImage *)image RecordID:(CKRecordID *)recordID
    
    {
    
     //获取容器
    
     CKContainer *container = [CKContainer defaultContainer];
    
     //获取公有数据库
    
     CKDatabase *database = container.publicCloudDatabase;
    
     [database fetchRecordWithID:recordID completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
    
     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];
    
     }
    
     NSDate *dateID = [NSDate dateWithTimeIntervalSinceNow:0];
    
     NSTimeInterval timeInterval = [dateID timeIntervalSince1970] * 1000; //*1000表示到毫秒级,这样可以保证不会同时生成两个同样的id
    
     NSString *idString = [NSString stringWithFormat:@"%.0f", timeInterval];
    
     NSString *filePath = [NSString stringWithFormat:@"%@/%@",tempPath,idString];
    
     NSURL *url = [NSURL fileURLWithPath:filePath];
    
     [imageData writeToURL:url atomically:YES];
    
     CKAsset *asset = [[CKAsset alloc]initWithFileURL:url];
    
     [record setObject:title forKey:@"title"];
    
     [record setObject:content forKey:@"content"];
    
     [record setValue:asset forKey:@"photo"];
    
     [database saveRecord:record completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
    
     if(error)
    
     {
    
     NSLog(@"修改失败 %@",error.description);
    
     }
    
     else
    
     {
    
     NSLog(@"修改成功");
    
     }
    
     }];
    
     }];
    
    }
    
    

    Demo

    先放一下demo的地址

    demo简单的制作了一个简单的cloud kit存储功能,一些交互没有完善,但是基本的增删改查功能都已经实现了。

    CloudKitDemo.gif

    以上就是Cloud Kit的简单使用。此文章仅供个人学习使用,如有不当,希望大佬指出。

    相关文章

      网友评论

        本文标题:iOS开发-iCloud的简单使用(3)-Cloud Kit的使

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