iOS學習筆記18 CoreData你懂的

執著丶執念發表於2018-06-02

###一、CoreData介紹 CoreData是iOS5之後新出來的的一個框架, 是對SQLite進行一層封裝升級後的一種資料持久化方式。 它提供了物件<-->關係對映的功能,即能夠將OC物件轉化為資料儲存到SQLite資料庫檔案中,同時也能將資料庫中的資料還原成OC物件。相較於SQLite,我們使用CoreData就不需要再編寫任何SQL語句,再也不去糾結SQL語句怎麼寫了O(∩_∩)O哈~。

###二、CoreData核心結構圖 ######先來張官方的圖:

這四者的關係圖

  • PersistentObjectStore:儲存持久物件的資料庫(例如SQLite,注意CoreData也支援其他型別的資料儲存,例如xml、二進位制資料等)。
  • ManagedObjectModel:物件模型,對應Xcode中建立的模型檔案。
  • PersistentStoreCoordinator:物件模型和實體類之間的轉換協調器,用於管理不同儲存物件的上下文。
  • ManagedObjectContext:物件管理上下文,負責實體物件和資料庫之間的互動。

######說了這麼多,可能你還是懵逼的,下面是我的理解圖:

我對CoreData的理解
最底層的就是PersistentObjectStore,也就是我們實際儲存資料的結構; 圖中的模型就是ManagedObjectModel,就是資料轉化為物件的模板; 以SQLite資料庫為例:

  • 讀取資料庫的資料時,資料庫資料先進入資料解析器,根據對應的模板,生成對應的關聯物件。
  • 向資料庫插入資料時,物件管理器先根據實體描述建立一個空物件,對該物件進行初始化,然後經過資料解析器,根據對應的模板,轉化為資料庫的資料,插入資料庫中。
  • 更新資料庫資料時,物件管理器需要先讀取資料庫的資料,拿到相互關聯的物件,對該物件進行修改,修改的資料通過資料解析器,轉化為資料庫的更新資料,對資料庫更新。

這些還是要在使用中進行加深理解

###三、CoreData使用 ####1. 新增框架

  • 新增CoreData.framework
  • #import匯入標頭檔案<CoreData/CoreData.h>

####2. 資料模板和物件模型 看上面的圖就知道,我們需要首先建立一個資料模板,即ManagedObjectModel ######下面是建立資料模板的步驟【是圖形化操作,所以都是圖片】:

第一步 建立資料模板檔案

第二步 點開資料模板檔案,新增實體,新增屬性

第三步 新增關係,可以控制是一對多還是多對多

點選style,可以檢視直觀的關係圖

第四步 根據資料模板建立物件模型檔案
點選Next,會進入一個資料模板檔案的選擇打鉤,再點Next,會進入一個實體的選擇打鉤,選完點Next就會自動生成物件模型檔案。
自動生成物件模型檔案

  • 所有的實體型別都繼承於NSManagedObject,每個NSManagedObject物件對應著資料庫中一條記錄。
  • 集合屬性(例如陣列)會自動生成訪問此屬性的分類方法。
  • 使用@dynamic代表具體屬性實現,具體實現細節不需要開發人員關心。

####3. 建立物件管理上下文 ######建立物件管理上下文ManagedObjectContext可以細分為:

  1. 載入模型檔案
  1. 指定資料儲存路徑
  2. 建立對應資料型別的儲存
  3. 建立管理物件上下方並指定儲存

######下面是例項程式碼:

- (NSManagedObjectContext *)createDbContext{
    //開啟模型檔案,引數為nil則開啟包中所有模型檔案併合併成一個
    NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    //建立資料解析器
    NSPersistentStoreCoordinator *storeCoordinator = 
            [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    //建立資料庫儲存路徑
    NSString *dir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES).firstObject;
    NSString *path = [dir stringByAppendingPathComponent:@"myDatabase.db"];
    NSURL *url = [NSURL fileURLWithPath:path];
    //新增SQLite持久儲存到解析器
    NSError *error;
    [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                   configuration:nil 
                                             URL:url 
                                         options:nil 
                                           error:&error];
    
    NSManagedObjectContext *context = nil;
    if( !error ){
        //建立物件管理上下文,並設定資料解析器
        context = [[NSManagedObjectContext alloc] init];
        context.persistentStoreCoordinator = storeCoordinator;
        NSLog(@"資料庫開啟成功!");
    }else{
        NSLog(@"資料庫開啟失敗!錯誤:%@",error.localizedDescription);
    }
    return context;
}
複製程式碼

####4. 插入資料 插入資料我們需要建立一個實體物件,並把這個物件關聯上物件管理器,我們建立實體物件需要使用到NSEntityDescription(實體描述類)的類方法 ######下面是實現程式碼:

- (void)addClassTest
{
    //新增一個物件
    Classes *classes = [NSEntityDescription insertNewObjectForEntityForName:@"Classes" 
                                                     inManagedObjectContext:self.context];
    classes.c_id = 301;
    classes.c_name = @"高三(1)班";
    NSError *error;
    //儲存上下文,這裡需要注意,增、刪、改操作完最後必須呼叫管理物件上下文的儲存方法,否則操作不會執行。
    if (![self.context save:&error]) {
        NSLog(@"新增過程中發生錯誤,錯誤資訊:%@!",error.localizedDescription);
    }
}
複製程式碼

####5. 刪除資料 ######刪除資料,只需要刪除關聯的物件就行了:

- (void)removeClasses:(Classes *classes){
    [self.context deleteObject:classes];
    NSError *error;
    if (![self.context save:&error]) {
        NSLog(@"刪除過程中發生錯誤,錯誤資訊:%@!",error.localizedDescription);
    }
}
複製程式碼

####6. 查詢資料 ######查詢資料需要處理查詢結果,要用到兩個類:

  • NSFetchRequest:獲取資料的請求
  • NSPredicate :請求的謂詞,也就是獲取資料的要求

######1. 查詢一個物件只有唯一一個關聯物件的情況 例如查詢使用者名稱為“Binger”的微博(一個微博只能屬於一個使用者),通過keypath查詢:

- (NSArray *)getStatusByUserName:(NSString *)name{
    //建立查詢請求
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Status"];
    //建立謂詞,設定獲取資料的條件
    request.predicate = [NSPredicate predicateWithFormat:@"user.name=%@",name];
    //執行物件管理上下文的查詢方法
    NSArray *array = [self.context executeFetchRequest:request error:nil];
    return  array;
}
複製程式碼

######2. 查詢一個物件有多個關聯物件的情況 例如查詢傳送微博內容中包含“Watch”並且使用者暱稱為“小娜”的使用者(一個使用者有多條微博)

- (NSArray *)getUsersByStatusText:(NSString *)text screenName:(NSString *)screenName{
    //建立查詢請求
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Status"];
    //設定查詢條件
    request.predicate = [NSPredicate predicateWithFormat:@"text LIKE '*Watch*'",text];
    //獲取查詢結果
    NSArray *statuses = [self.context executeFetchRequest:request error:nil];
    //下面是用謂詞對上面的結果進行過濾
    NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"user.screenName=%@",screenName];
    //對查詢結果再進行過濾
    NSArray *users = [statuses filteredArrayUsingPredicate:userPredicate];
    return users;
}
複製程式碼

####7. 修改資料 只需要拿到對應的關聯物件,直接修改,然後儲存

- (void)modifyClasses:(Classes *)classes
{    
	classes.name = @"吊炸天畢業(1)班";
    NSError *error;
    if (![self.context save:&error]) {
		NSLog(@"修改過程中發生錯誤,錯誤資訊:%@",error.localizedDescription);    
	}
}
複製程式碼

###四、CoreData除錯 ######事實上在Xcode中是支援CoreData除錯的,具體操作:

  • Product->Scheme
  • Scheme->Edit Scheme
  • Edit Scheme->Run
  • Run->Arguments 依次新增兩個引數(注意引數順序不能錯):

CoreData除錯設定
然後在執行程式過程中,如果操作了資料庫,就會將SQL語句列印在輸出皮膚。

注意:如果模型發生了變化,此時可以重新生成實體類檔案,但是所生成的資料庫並不會自動更新,這時需要考慮重新生成資料庫並遷移原有的資料。

######這一節感覺寫的不好,很多東西沒法寫太細,很多概念也不好理解,希望大家體諒,有建議可以在下方的評論區提出,O(∩_∩)O哈!

相關文章