iOS 开发学习

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

2018-01-23  本文已影响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的方式来存储和获取数据。目前可以支持如下格式的数据:

其中图片的数据类型需要先初始化一个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

添加的内容有:

添加 indexs

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

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

CloudKitAddIndex.png

添加的内容有:

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

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的简单使用。此文章仅供个人学习使用,如有不当,希望大佬指出。

上一篇 下一篇

猜你喜欢

热点阅读