iOS學習筆記18-CoreData你懂的

一、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哈!
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,646評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,595評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,560評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,035評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,814評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,224評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,301評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,444評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,988評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,804評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,998評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,544評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,237評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,665評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,927評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,706評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,993評論 2 374

推薦閱讀更多精彩內容