iOS項目iCloud及CloudKit Dashboard運用

CloudKit是蘋果推出的基於iCloud的一個雲端數據存儲服務.其 主要由下面兩部分組成:git

一個儀表web頁面,用於管理公開數據的記錄類型.github

一組API接口,用於iCloud和設備之間的數據傳遞.web

 

一:首先在XCode上面打開關於iCloud功能數據庫

1:進入對應的項目Targets 中的Capabilities 選項卡,打開關於iCloud功能;若是勾選iCloud Documents或CloudKit會自動生成一個帶iCloud.開頭的Containers,要配置證書支持;CloudKit Dashboard則能夠直接跳轉到Web配置關於iCloud的內容;而關於Steps則是配置的步驟是否都成功;微信

 

 

二:關於證書如何配置支持iCloud功能app

1:進入蘋果證書管理後臺中的Identifiers裏有個iCloud Containers菜單框架

 

由於實例中的Bundle Identifier的名字wjy.com.MobileProject;因此在這邊建立一個iCloud.wjy.com.MobileProject的ID值;都是前面增長一個iCloud爲開頭;app的bundle id須要與iCloud容器相對應, iCloud容器名必須是惟一的,由於這是Cloudkit用來訪問數據所使用的全局標識符。因爲iCloud容器名包含bundle id,所以bundle id也必須是惟一的(這就是爲什麼須要修改com.raywendrelich.BabiFud)。 fetch

爲了讓entitlements起做用,須要在App的證書、標識符與配置文件中ID的部分列出app/bundle id。這意味着標識的證書使用了設置的team id與app id,從中可獲得iCloud容器的id。若已經在一個可用的開發者帳號中標識了的話Xcode會自動完成這一切。不巧的是,這有時是不一樣步的,須要更新ID-使用iCloud功能面板修改CloudKit容器ID。不然的話須要修改info.plist文件或BabiFud.entitlements文件來確保id values與所設置的bundle id一致。ui

2:建立完上面的ID後,一樣進行Identifiers裏的App IDs,找到咱們當前的App ID而後對它進行編輯atom

打開iCloud的功能選擇,而且選擇Include CloudKit support,這邊這時會有一個警告出現,選擇右邊的Edit進行編輯

這時會有剛纔建立好的那個iCloud ID能夠選擇綁定;選擇好之後外面的警告也會消除;而後生成對應的描述文件安裝後,XCode上面的步驟報錯也會消除;

 

三:設置iCloud的數據

1:要進入CloudKit Dashboard操做有兩種方式,第一種如上面第一點所說能夠直接點CloudKit Dashboard進入,另外一種就是進入蘋果帳號後臺也有一個相應的菜單;

2:進入CloudKit Dashboard能夠看到以下的頁面

 

2.1 SCHEMA :

CloudKit容器的高級類:Record Types, Security Roles, 和Subscription Types,其中主要使用的是Record Types;

一個Record Type用來定義一個單獨的記錄(能夠理解爲一個數據模型),至關於存儲數據的模板,和數據庫的表結構相似;

2.2 PUBLIC DATA 和 PRIVATE DATA

就是你保存數據的地方,開發者能夠查看全部的共享數據,可是隻能看到本身的私密數據,沒法看到用戶的私密數據;這裏沒有顯示PRIBATE DATA,其結構和PUBLIC DATA是同樣的;

User Records 記錄一些當前使用者的信息;

Default Zone :這裏能夠查看數據的詳細信息,也是後面主要使用的;

2.3 ADMIN 主要是管理開發者團隊權限的,這裏不作過多介紹;

3:切回Record Type選項,點擊右邊欄的左上角的 "+ ",新增一個模型:

輸入模型名稱: 默認只有一個StringField的屬性(這裏暫且這麼稱呼吧),能夠點擊下面的Add Field... 新增屬性列表;

一樣能夠選擇屬性的類型,以下圖:

設置完成後,點擊右下角的 Save按鈕便可保存!這樣,一個模型就創建好了;存儲類型的數據:

1. NSData (single bytes)  
2. NSDate (date and time)  
3. NSNumber (both Int and Double)  
4. NSString (or String in Swift)  
5. NSArray (list)  
6. CKReference (used to create relationships between objects)  
7. CLLocation (location)  
8. CKAsset (file)  

5:回到Default Zone,中間藍色區域的右上角的名稱旁有個倒三角,這裏能夠選擇使用(查詢)哪一個模型下的數據:

 

6:若是要存是圖片字段記得選Asset類型

 

注意:1 Public Record ,1 Private Record,意思是:使用模型Note的有一條公共數據,一條隱私數據,因爲我登錄的iCloud帳號和開發者帳號不同,至關因而用戶帳號,因此這裏是看不到那個隱私數據的

 

四:代碼操做iCloud功能

1:首先引入CloudKit.framework系統框架,並引入命名空間#import <CloudKit/CloudKit.h> 就能夠進行操做

2:首先是判斷手機中的iCloud功能是否開啓,以下面若是有值則表示已經開啓的iCloud功能;

id cloudUrl=[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];

這個方法接受一個參數, 就是要獲取的容器標識。 所謂容器標識, 大多數應用只會用到一個 iCloud 容器,因此咱們這裏傳入 nil, 就表明默認獲取第一個可用的容器。這個方法內部會查找當前應用擁有的 iCloud 容器, 若是找到就會返回這個容器的 URL, 證實當前應用的 iCloud 容器可用。 若是找不到,就會返回 nil, 證實當前應用的 iCloud 不可用。

注意: iCloud 容器和你 App 文件沙盒, 在 iOS 文件系統中實際上是分別存放在兩個不一樣的地方的:

iCloud 文件路徑格式 file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~xxx~aaa/Documents

App 沙盒文件路徑格式 file:///var/mobile/Containers/Data/Application/3B4376B3-89B5-3342-8057-3450D4224518/Documents/

因而可知, 這也是爲何 iCloud 和 Sandbox 文件路徑訪問須要兩套不一樣的方式的緣由了。

3:增長一條記錄,能夠給它一個固定的recordID,就像數據表的主鍵同樣,查找、更新跟刪除有用;

-(void)addCloudDataWithPublic:(BOOL)isPublic recordID:(NSString *)recordID name:(NSString *)name password:(NSString *)password
{
    //CloudKit給應用程序分配部分空間,用於存儲數據,首先要獲取這個存儲空間,這裏咱們直接獲取了默認的存儲器(能夠自定義存儲器):
    CKContainer *container=[CKContainer defaultContainer];
    CKDatabase *database;
    if (isPublic) {
        database=container.publicCloudDatabase; //公共數據
    }
    else
    {
        database=container.privateCloudDatabase;//隱藏數據
    }
    
    //建立主鍵ID  這個ID能夠到時查找有用到
    CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID];
    //建立CKRecord 保存數據
    CKRecord *noteRecord = [[CKRecord alloc]initWithRecordType:@"User" recordID:noteId];
    
    //設置數據
    [noteRecord setObject:name forKey:@"name"];
    [noteRecord setObject:password forKey:@"password"];
    
    //保存操做
    [database saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
        if (!error) {
            [self showAlertMessage:@"保存成功"];
        }
    }];
}

4:假如要保存帶有圖片的字段,須要用到CKAsset,他的初始化須要一個URL,因此這裏,我先把圖片數據保存到本地沙盒,生成一個URL,而後再去建立CKAsset:

//增長帶圖片的提交 圖片的保存,須要用到CKAsset,他的初始化須要一個URL,因此這裏,我先把圖片數據保存到本地沙盒,生成一個URL,而後再去建立CKAsset:
-(void)saveImageDataWithPublic:(BOOL)isPublic recordID:(NSString *)recordID name:(NSString *)name password:(NSString *)password
{
    //保存圖片 圖片的保存,須要用到CKAsset,他的初始化須要一個URL,因此這裏,我先把圖片數據保存到本地沙盒,生成一個URL,而後再去建立CKAsset:
    UIImage *image=[UIImage imageNamed:@"icloudImage"];
    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,@"iCloudImage"];
    NSURL *url = [NSURL fileURLWithPath:filePath];
    [imageData writeToURL:url atomically:YES];
    
    CKAsset *asset = [[CKAsset alloc]initWithFileURL:url];
    
    //與iCloud進行交互
    CKContainer *container=[CKContainer defaultContainer];
    CKDatabase *database;
    if (isPublic) {
        database=container.publicCloudDatabase; //公共數據
    }
    else
    {
        database=container.privateCloudDatabase;//隱藏數據
    }
    
    //建立主鍵ID  這個ID能夠到時查找有用到
    CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID];
    //建立CKRecord 保存數據
    CKRecord *noteRecord = [[CKRecord alloc]initWithRecordType:@"User" recordID:noteId];
    
    //設置數據
    [noteRecord setObject:name forKey:@"name"];
    [noteRecord setObject:password forKey:@"password"];
    [noteRecord setObject:asset forKey:@"userImage"];
    
    //保存操做
    [database saveRecord:noteRecord completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
        if (!error) {
            [self showAlertMessage:@"保存成功"];
        }
    }];
}

5:查找單條記錄的功能,經過recordID進行

//查找單條記錄
-(void)searchRecordWithRecordID:(NSString *)recordID withFormPublic:(BOOL)isPublic
{
    //得到指定的ID
    CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID];
    
    //得到容器
    CKContainer *container=[CKContainer defaultContainer];
    
    //得到數據的類型 是公有仍是私有
    CKDatabase *database;
    if (isPublic) {
        database=container.publicCloudDatabase;
    }
    else
    {
        database=container.privateCloudDatabase;
    }
    
    __weak typeof(self)weakSelf = self;
    //查找操做
    [database fetchRecordWithID:noteId completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
        NSString *message=[NSString stringWithFormat:@"得到RecordID爲%@ 的數據:%@,%@",recordID,[record objectForKey:@"name"],[record objectForKey:@"password"]];
        [weakSelf showAlertMessage:message];
    }];
}

6:查詢多條記錄的功能,用到的謂詞進行

//查找多條記錄(能夠用謂詞進行)
-(void)searchRecordWithFormPublic:(BOOL)isPublic withRecordTypeName:(NSString *)recordTypeName
{
    CKContainer *container=[CKContainer defaultContainer];
    //得到數據的類型 是公有仍是私有
    CKDatabase *database;
    if (isPublic) {
        database=container.publicCloudDatabase;
    }
    else
    {
        database=container.privateCloudDatabase;
    }
    
    NSPredicate *predicate=[NSPredicate predicateWithValue:YES];
    CKQuery *query=[[CKQuery alloc]initWithRecordType:recordTypeName predicate:predicate];
    
    __weak typeof(self)weakSelf = self;
    [database performQuery:query inZoneWithID:nil completionHandler:^(NSArray<CKRecord *> * _Nullable results, NSError * _Nullable error) {
        [weakSelf showAlertMessage:[NSString stringWithFormat:@"%@",results]];
    }];
}

7:更新一條記錄首先要查找出該條記錄,再對它進行修改,若是對應的鍵值存在進修改其值,若是鍵值不存在則增長新的類型字段;

//更新一條記錄 首先要查找出這一條  而後再對它進行修改
-(void)updateRecordWithFormPublic:(BOOL)isPublic withRecordTypeName:(NSString *)recordTypeName withRecordID:(NSString *)recordID
{
    //得到指定的ID
    CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID];
    
    //得到容器
    CKContainer *container=[CKContainer defaultContainer];
    
    //得到數據的類型 是公有仍是私有
    CKDatabase *database;
    if (isPublic) {
        database=container.publicCloudDatabase;
    }
    else
    {
        database=container.privateCloudDatabase;
    }
    
    __weak typeof(self)weakSelf = self;
    //查找操做
    [database fetchRecordWithID:noteId completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
        if (!error) {
            
            //對原有的健值進行修改
            [record setObject:@"aa123456789" forKey:@"password"];
            //若是健值不存在 則會增長一個
            [record setObject:@"" forKey:@"gender"];
            
            [database saveRecord:record completionHandler:^(CKRecord * _Nullable record, NSError * _Nullable error) {
                if (!error) {
                    [weakSelf showAlertMessage:@"修改保存成功"];
                }
                else
                {
                    [weakSelf showAlertMessage:[NSString stringWithFormat:@"出錯誤 :%@",error]];
                }
            }];
            
        }
    }];
}

8:刪除一條記錄

//刪除記錄
-(void)deleteRecordWithFormPublic:(BOOL)isPublic withRecordID:(NSString *)recordID
{
    //得到指定的ID
    CKRecordID *noteId=[[CKRecordID alloc]initWithRecordName:recordID];

    //得到容器
    CKContainer *container=[CKContainer defaultContainer];
    
    //得到數據的類型 是公有仍是私有
    CKDatabase *database;
    if (isPublic) {
        database=container.publicCloudDatabase;
    }
    else
    {
        database=container.privateCloudDatabase;
    }
    
    __weak typeof(self)weakSelf = self;
    [database deleteRecordWithID:noteId completionHandler:^(CKRecordID * _Nullable recordID, NSError * _Nullable error) {
        if (!error) {
            [weakSelf showAlertMessage:@"刪除成功"];
            return;
        }
        [weakSelf showAlertMessage:[NSString stringWithFormat:@"刪除失敗 %@",error]];
    }];
    
}

 五:操做實例

編寫一個關於在同一臺手機上免登陸的實例,主要原理是經過獲取手機設備惟一碼,而後經過iCloud保存到雲端,在刪除APP後再安裝後就能夠直接從雲端得到用戶跟密碼;會不斷完善此實例,若是感興趣能夠點星並關注,會接着編寫關於iCloud關於文件的同步功能;注意證書能夠換成自個的,步驟如上:

源代碼地址:https://github.com/wujunyang/iCloudProject

 

最近有個妹子弄的一個關於擴大眼界跟內含的訂閱號,天天都會更新一些深度內容,在這裏若是你感興趣也能夠關注一下(嘿對美女跟知識感興趣),固然能夠關注後輸入:github 會有個人微信號,若是有問題你也能夠在那找到我;固然不感興趣無視此信息;

相關文章
相關標籤/搜索