上篇文章[iCloud]項目內(nèi)啟用iCloud及CloudKit Dashboard介紹簡單介紹了怎樣在項目中啟用iCloud,以及一個web端的預覽存儲數(shù)據(jù)的工具.今天我來介紹一下實現(xiàn)數(shù)據(jù)存儲到iCloud的框架: CloudKit.framework.
CloudKit存儲數(shù)據(jù)的結(jié)構(gòu)類似數(shù)據(jù)庫,下面的很多操作你都會有似曾相識的感覺;
首先.我們來看一下,它能存儲哪些類型的數(shù)據(jù):
- NSData (single bytes)
- NSDate (date and time)
- NSNumber (both Int and Double)
- NSString (or String in Swift)
- NSArray (list)
- CKReference (used to create relationships between objects)
- CLLocation (location)
- CKAsset (file)
CK開頭的數(shù)據(jù)類型,是CloudKit.framework的一部分.這里我主要介紹字符串的處理,日期和資源(一種特殊情況),上面的CKReference和CLLocation(特殊類型)暫且不在討論范圍,如果有興趣,可以參考官網(wǎng)資料學習...
本次討論,主要是實現(xiàn)數(shù)據(jù)的增刪改查操作,更多功能可參考官方API.
1. 添加數(shù)據(jù)
CloudKit給應(yīng)用程序分配部分空間,用于存儲數(shù)據(jù),首先要獲取這個存儲空間,這里我們直接獲取了默認的存儲器(可以自定義存儲器):
CKContainer *container = [CKContainer defaultContainer];
然后獲取他的數(shù)據(jù)種類,也就是你要存的數(shù)據(jù)是隱私數(shù)據(jù),還是對外公開的公共數(shù)據(jù):
CKDatabase *database = container.publicCloudDatabase;//公共數(shù)據(jù)
CKDatabase *database = container.privateCloudDatabase;//隱私數(shù)據(jù)
接著,就要設(shè)置要保存的數(shù)據(jù),每一個數(shù)據(jù)庫都有一個唯一的字段來標識唯一的一條數(shù)據(jù),這里也不例外,就是CKRecordID:
//創(chuàng)建主鍵id
CKRecordID *noteId = [[CKRecordID alloc]initWithRecordName:@"IDname"];
每一條記錄(數(shù)據(jù)),就是一個CKRecord;
創(chuàng)建一條記錄(數(shù)據(jù)):
//創(chuàng)建CKRecord 保存數(shù)據(jù)
CKRecord *noteRecord = [[CKRecord alloc]initWithRecordType:@"recordType" recordID:noteId];
這里的recordType可以理解為一個數(shù)據(jù)模型,這兒傳的就是模型的名稱;
設(shè)置數(shù)據(jù),CKRecord的使用和字典非常相似,如下保存一個字符串:
noteRecord setObject:@"value" forKey:@"key"]
關(guān)于圖片的保存,需要用到CKAsset,他的初始化需要一個URL,所以這里,我先把圖片數(shù)據(jù)保存到本地沙盒,生成一個URL,然后再去創(chuàng)建CKAsset:
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];
}
NSString *filePath = [NSString stringWithFormat:@"%@/%@",tempPath,[self LZCreatRedomString]];
NSURL *url = [NSURL fileURLWithPath:filePath];
[imageData writeToURL:url atomically:YES];
CKAsset *asset = [[CKAsset alloc]initWithFileURL:url];
這樣一條數(shù)據(jù)就準備好了,最后,將他寫入iCloud:
[database saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
if (!error) {
NSLog(@"保存成功");
}];
這樣在CloudKit Dashboard上的Record Types中可以看到新添加的數(shù)據(jù)模型,在PUBLIC DATA中的Default Zone可以看到這條記錄的詳細信息;
2. 查詢記錄(數(shù)據(jù))
2.1 查詢所有的記錄(數(shù)據(jù))
查詢數(shù)據(jù),同樣需要獲取當前的數(shù)據(jù)的存儲位置:
CKContainer *container = [CKContainer defaultContainer];
CKDatabase *database = container.publicCloudDatabase
執(zhí)行查詢的操作,用到了另一個類: CKQuery
NSPredicate *predicate = [NSPredicate predicateWithValue:YES];
CKQuery *query = [[CKQuery alloc]initWithRecordType:@"recordType" predicate:predicate];
這里的第一個就是你要查詢的是那種類型的數(shù)據(jù),第二個參數(shù)是查詢條件,就是一個謂詞;
開始查詢:
[database performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {
NSLog(@"%@",results);
}];
這里的results就是包含當前數(shù)據(jù)模型下的所有記錄的數(shù)組,其成員為CKRecord對象;
2.2. 查詢單個記錄
單條數(shù)據(jù)的查詢就比較簡單了,只需要知道他的CKRecordID就行了:
//創(chuàng)建主鍵id
CKRecordID *noteId = [[CKRecordID alloc]initWithRecordName:@"IDName"];
//獲取容器
CKContainer *container = [CKContainer defaultContainer];
//獲取公有數(shù)據(jù)庫
CKDatabase *database = container.publicCloudDatabase
[database fetchRecordWithID:noteId completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",record);
});
}];
3. 修改記錄(數(shù)據(jù))
修改一個記錄,需要先獲取這個記錄,然后進行相應(yīng)的修改,這里假設(shè)已經(jīng)獲取到了這條數(shù)據(jù),我直接進行修改:
[record setObject:@"改變一下" forKey:@"key"];
[record setObject:@"原模型沒有這個字段" forKey:@"newKey"];
需要注意,上面的newKey,原先的數(shù)據(jù)模型(recordType)里是沒有這個字段的,如果修改的時候設(shè)置了,相當于新加一個字段,這樣也是可以的;
然后,再執(zhí)行保存操作:
//獲取容器
CKContainer *container = [CKContainer defaultContainer];
//獲取公有數(shù)據(jù)庫
CKDatabase *database = container.publicCloudDatabase
[database saveRecord:record completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
NSLog(@"修改成功");
}];
這樣原先的記錄就被修改了,而且多了一個字段;
4. 刪除記錄(數(shù)據(jù))
同樣,刪除也是以那個唯一的CKRecordID來進行的,直接給出代碼:
CKRecordID *recordID = record.recordID;
CKContainer *container = [CKContainer defaultContainer];
CKDatabase *database = container.publicCloudDatabase;
[database deleteRecordWithID:recordID completionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
NSLog(@"刪除成功");
}];
這樣就刪除成功了;
總結(jié):
- a.這里只是進行了簡單的增刪改查操作,也是最基本的操作,CloudKit中還有許多其他高級的操作,可以參考其官方文檔學習;
- b.上面的增刪改查的結(jié)果,都是在子線程進行的,如果需要操作UI,請在回調(diào)的block內(nèi)回到主線程進行;
- c.所有操作的變化,都可以在CloudKit Dashboard上查看;
- d.所有的操作都是在開發(fā)環(huán)境下進行的,如果要應(yīng)用到項目中,還需要進行很多的配置,包括證書的設(shè)置;
- e.筆者也是初步接觸這個框架,不足之處還請指教!
參考資料
http://www.devtf.cn/?p=574
官方文檔 1
官方文檔 2
以及XcodeAPI說明文檔.