iOS開發(fā)-iCloud的簡單使用(3)-Cloud Kit的使用

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

比起前邊的兩種,Cloud kit更像是一個數(shù)據(jù)庫。蘋果會提供一個dashboard作為云存儲的管理端。

Cloud Kit 基礎(chǔ)

cloud kit一共有7個基礎(chǔ)類,簡單了解一下這些基礎(chǔ)類接下來的使用就比較容易理解了。

CKContainer

CKContainer類似于應(yīng)用運(yùn)行時的沙盒,一個應(yīng)用只能訪問自己的沙盒,同樣的,一個應(yīng)用也只能訪問自己的Container。

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


 CKContainer *container = [CKContainer defaultContainer];

CKDatabase

CKDatabase很明顯就是數(shù)據(jù)庫,他擁有私有數(shù)據(jù)庫公有數(shù)據(jù)庫兩種類型。用戶只能訪問自己的私有數(shù)據(jù)庫,一些不敏感的數(shù)據(jù)也可以存儲在公有數(shù)據(jù)庫中。


 //公有數(shù)據(jù)庫

 CKDatabase *datebase = container.publicCloudDatabase;

 //私有數(shù)據(jù)庫

 CKDatabase *datebase = container.privateCloudDatabase;

CKRecord

CKRecord就是數(shù)據(jù)庫中的一條數(shù)據(jù)記錄,他通過key-value的方式來存儲和獲取數(shù)據(jù)。目前可以支持如下格式的數(shù)據(jù):

  • NSString(swift中的Sting)

  • NSNumber

  • NSData

  • NSDate

  • CLLocation

  • CKReference

  • CKAsset

其中圖片的數(shù)據(jù)類型需要先初始化一個URL,然后把圖片保存到本地沙盒,生成URL,再創(chuàng)建CKAsset來存儲。

CKRecordZone

CKRecordZone是用來保存Record的。所有的Record都是保存在這里,應(yīng)用有一個默認(rèn)的zone,也可以自定義zone。

CKRecordIdentifier

CKRecordIdentifierRecord的唯一標(biāo)示,用來確定Record在數(shù)據(jù)庫中的位置。

CKReference

CKReference是一種引用關(guān)系。

CKAsset

CKAsset 為資源文件,比如之前提到的照片就是用這種方式存儲的。

CloudKit Dashboard

更新:

這里還有一個WWDC的視頻介紹Cloud dashboard

Build Better Apps with CloudKit Dashboard]

CloudKit Dashboard 的入口在這里:

CloudKitDashboardEnter.png

你也可以直接訪問地址

這個界面好像更新過了,和網(wǎng)上很多教程的樣式都不太一樣。新的界面長這樣:

CloudKitDashboardWeb.png

新的界面包括開發(fā)版和產(chǎn)品版(線上版)兩種,在開發(fā)的時候我們就只針對左邊的開發(fā)版進(jìn)行操作就可以了。無論是那個版本,都有五個相同的入口。

Data

Cloud kit的數(shù)據(jù)管理中心入口。在這里可以進(jìn)行數(shù)據(jù)的字段,索引等內(nèi)容設(shè)定。

Logs

查看Cloud kit的服務(wù)日志,顯示數(shù)據(jù)庫操作,推送通知以及對應(yīng)環(huán)境中的其他活動。

Telemetry

查看對應(yīng)環(huán)境中服務(wù)器端性能和數(shù)據(jù)庫利用率的圖表。

Public Database Usage

查看公共數(shù)據(jù)庫的使用情況圖標(biāo),包括活躍用戶、請求頻率等。

Api Access

管理API令牌和服務(wù)器密鑰,允許對應(yīng)環(huán)境進(jìn)行web服務(wù)調(diào)用。

使用

這次我們只講簡單的操作,所以本篇文章就只使用 Data中的部分功能。

創(chuàng)建 RECORD TYPE

首先點(diǎn)擊Data , RECORD TYPE , Create New Type創(chuàng)建一個新的RECORD TYPE。

CloudKitCreateRecordType.png

這里注意,我們的RECORD TYPE Name 是Note,這個在之后代碼里操作非常重要,所以記得不要寫錯了。

添加 Field

有了表,接下來就是添加字段了。點(diǎn)擊Add Field 然后輸入字段名,選擇類型就可以了。這里可以一次性添加多條,添加完點(diǎn)擊保存就可以了。

CloudKitAddField.png

添加的內(nèi)容有:

  • title String

  • content String

  • photo Asset

添加 indexs

為了搜索更方便一些,我們添加一些索引。

點(diǎn)擊INDEXS,選擇我們剛剛添加的Note,然后添加索引,添加的索引類型有QUERYABLE,SEARCHABLE,SORTABLE。

CloudKitAddIndex.png

添加的內(nèi)容有:

  • title QUERYABLE

  • title SEARCHABLE

  • title SORTABLE

  • content QUERYABLE

  • content SEARCHABLE

  • content SORTABLE

  • recordName QUERYABLE

添加完就是這樣的,對照一下看看有沒有添加錯啊。

CloudKitAddIndexFinished.png

添加數(shù)據(jù)

接下來,我們就可以給表里添加數(shù)據(jù)了。

選擇RECORD ,確認(rèn)LOAD RECORDS FROMQUERY FOR RECORDS OF TYPE 都正確了之后,點(diǎn)擊Creat New Record...,在右邊輸入想要插入的數(shù)據(jù),添加個幾條就可以了。

CloudKitAddRecord.png

查詢數(shù)據(jù)

隨便添加幾條數(shù)據(jù)之后,還是在這個頁面,點(diǎn)擊左側(cè)的Query Records,就可以查詢到數(shù)據(jù)了。

CloudKitQueryRecords.png

到此,Cloud Dashboard的簡單使用就介紹到這,接下來我們看看通過代碼怎么來操作Cloud kit。

擼起袖子寫代碼吧。

通過代碼操作 Cloud Kit

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


#import <CloudKit/CloudKit.h>

添加數(shù)據(jù)

首先創(chuàng)建一個容器


 //獲取容器

 CKContainer *container = [CKContainer defaultContainer];

然后獲取數(shù)據(jù)庫,這里我們使用公有數(shù)據(jù)庫


 //公共數(shù)據(jù)

 CKDatabase *datebase = container.publicCloudDatabase;

接下來創(chuàng)建一條數(shù)據(jù),這里的RECORD_TYPE_NAME就是之前創(chuàng)建表的名字Note


 //創(chuàng)建保存數(shù)據(jù)

 CKRecord *noteRecord = [[CKRecord alloc] initWithRecordType:RECORD_TYPE_NAME];

添加數(shù)據(jù)是使用Key-value的方式。


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

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

這里要特殊注意的是圖片的處理,我們先要創(chuàng)建一個URL,然后把圖片數(shù)據(jù)保存到沙盒中,生成一個URL,再創(chuàng)建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轉(zhuǎn)UIImage的方法:


CKAsset *asset = [record objectForKey:@"photo"];

UIImage *image = [UIImage imageWithContentsOfFile:asset.fileURL.path];

這樣數(shù)據(jù)的內(nèi)容就處理好了,接下來我們只要把它保存起來就可以咯。


 [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];

 //公共數(shù)據(jù)

 CKDatabase *datebase = container.publicCloudDatabase;

// //私有數(shù)據(jù)

// CKDatabase *datebase = container.privateCloudDatabase;

// //創(chuàng)建主鍵

// CKRecordID *noteID = [[CKRecordID alloc] initWithRecordName:@"NoteID"];

 //創(chuàng)建保存數(shù)據(jù)

 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);

 }

 }];

}

查詢數(shù)據(jù)

查詢所有數(shù)據(jù)

查詢數(shù)據(jù)同樣,我們也要先獲取容器和數(shù)據(jù)庫。


 //獲取位置

 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];

準(zhǔn)備好了,接下來就可以調(diào)用查詢方法了,獲取到的results就是獲取到數(shù)據(jù)的數(shù)組了,這里我用了通知的方法把查詢到的數(shù)據(jù)傳出去。


 //開始查詢

 [database performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {

 NSLog(@"%@",results);

 //把數(shù)據(jù)做成字典通知出去

 NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:results forKey:@"key"];

 [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataQueryFinished" object:nil userInfo:userinfoDic];

 }];

整個代碼合起來就是這樣的:


//查詢數(shù)據(jù)

+ (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);

 //把數(shù)據(jù)做成字典通知出去

 NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:results forKey:@"key"];

 [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataQueryFinished" object:nil userInfo:userinfoDic];

 }];

}

查詢單個數(shù)據(jù)

同樣也是獲取容器和數(shù)據(jù)庫。


 //獲取位置

 CKContainer *container = [CKContainer defaultContainer];

 CKDatabase *database = container.publicCloudDatabase;

然后我們需要獲取查詢的數(shù)據(jù)的RecordID。


 [database fetchRecordWithID:recordID completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {

 dispatch_async(dispatch_get_main_queue(), ^{

 NSLog(@"%@",record);

 //把數(shù)據(jù)做成字典通知出去

 NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:record forKey:@"key"];

 [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataSingleQueryFinished" object:nil userInfo:userinfoDic];

 });

 }];

合起來代碼就是這樣的:


//查詢單條數(shù)據(jù)

+ (void)querySingleRecordWithRecordID:(CKRecordID *)recordID

{

 //獲取容器

 CKContainer *container = [CKContainer defaultContainer];

 //獲取公有數(shù)據(jù)庫

 CKDatabase *database = container.publicCloudDatabase;

 [database fetchRecordWithID:recordID completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {

 dispatch_async(dispatch_get_main_queue(), ^{

 NSLog(@"%@",record);

 //把數(shù)據(jù)做成字典通知出去

 NSDictionary *userinfoDic = [NSDictionary dictionaryWithObject:record forKey:@"key"];

 [[NSNotificationCenter defaultCenter] postNotificationName:@"CloudDataSingleQueryFinished" object:nil userInfo:userinfoDic];

 });

 }];

}

刪除數(shù)據(jù)

刪除數(shù)據(jù)同樣,我們也要先獲取容器和數(shù)據(jù)庫。


 //獲取位置

 CKContainer *container = [CKContainer defaultContainer];

 CKDatabase *database = container.publicCloudDatabase;

然后,在刪除數(shù)據(jù)時,要獲取到你要刪除的數(shù)據(jù)的RecordID,之后直接執(zhí)行刪除方法即可


 [database deleteRecordWithID:recordID completionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {

 if(error)

 {

 NSLog(@"刪除失敗");

 }

 else

 {

 NSLog(@"刪除成功");

 }

 }];

合起來代碼就是這樣


//刪除數(shù)據(jù)

+ (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(@"刪除成功");

 }

 }];

}

修改數(shù)據(jù)

還是那句話,先獲取容器


 CKContainer *container = [CKContainer defaultContainer];

 CKDatabase *database = container.publicCloudDatabase;

其實(shí)修改數(shù)據(jù)就是重新把數(shù)據(jù)寫入。在寫入的時候如果選擇之前沒有的key,就相當(dāng)于新增了一個字段。然后執(zhí)行保存操作就可以了。

直接上全部的代碼好了:


//修改數(shù)據(jù)

+ (void)changeCloudKitWithTitle:(NSString *)title content:(NSString *)content photoImage:(UIImage *)image RecordID:(CKRecordID *)recordID

{

 //獲取容器

 CKContainer *container = [CKContainer defaultContainer];

 //獲取公有數(shù)據(jù)庫

 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存儲功能,一些交互沒有完善,但是基本的增刪改查功能都已經(jīng)實(shí)現(xiàn)了。

CloudKitDemo.gif

以上就是Cloud Kit的簡單使用。此文章僅供個人學(xué)習(xí)使用,如有不當(dāng),希望大佬指出。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容