(一)CoreData - 基本使用

(一)CoreData - 基本使用

@(HTML5秘籍)[Objective-c, iOS, 本地存儲]


@一張占位圖,心曠神怡的開始閱讀吧

題目雖然說的是快速入門,但是CoreData是一門很博大精深的技術,還是不要妄想幾天之內能融會貫通。接下來幾篇文章會由淺入深,逐步講解如何使用并掌握CoreData

最近一直在找一些關于日程管理的軟件,有一些感覺還不錯的,但是總覺得自己想要一些功能都沒有,所以干脆就下手自己寫一個自己的。由于沒有后臺服務器做接口,一些數據只能暫時做本地存儲。在技術選型的時候做了一些調查,因為之前做過PHP,對SQL印象蠻好的。但是對于一個移動端應用來說,基本不需要大量的存儲數據,因此在FMDB,Realm和CoreData之間,選擇了蘋果的親兒子CoreData。

[TOC]

封裝CoreData管理工具

1. 創建一個自帶CoreData代碼的工程

在Xcode創建工程的時候,就可以創建一個帶有CoreData的工程,在APPdelegate中會生成關于CoreData的代碼。


@創建帶有CoreData的工程

下圖是Xcode7自動創建的CoreData代碼,Xcode 8 做了修改,我們先說一下舊版的怎么玩,然后再看看新版怎么弄。

@Xcode 7自動創建的CoreData代碼1

@Xcode 7自動創建的CoreData代碼2

雖然說已經生成了這些代碼,但是還是不能直接用,我們需要將代碼重新封裝一下。

2. 簡單封裝CoreData管理類

① 創建一個繼承于NSObject的類 LTCoreDataManager

② 寫一個單例作為初始化方法

+ (LTCoreDataManager *)shareLTCoreDataManager
{
    static LTCoreDataManager *manager = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[LTCoreDataManager alloc] init];
    });

    return manager;
}

③ 將自動生成的代碼粘貼到 LTCoreDataManager.m 中

④ 在 LTCoreDataManager.h 中加入方法聲明

+ (LTCoreDataManager *)shareLTCoreDataManager;

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

⑤ 注意:應在 LTCoreDataManager.h 中引入 <CoreData/CoreData.h>

創建CoreData模型文件

1.構建模型文件

在創建工程的時候,如果選擇了使用CoreData,Xcode會自動生成一個模型文件,模型文件的后綴為.xcdatamodeld。如果沒有選擇自動生成模型文件,我們可以手動創建一個模型文件Command + N,選擇 Core Data -> Data Model -> Next

@創建好的模板

左側有三個選項,entitiesfetch requestsconfigurations

2.創建實體

長按左下方的 Add Entity 按鈕,會彈出菜Add EntityAdd Fetch RequestAdd Configuration。選擇 Add Entity創建一個實體,命名為Plan。如下圖所示

@Plan Entity

右側對應著Attributes(屬性)、Relationships(關聯關系)、Fetched Properties(獲取操作)。
首先,添加兩個屬性,planName:type 為 String,planId:type 為 Integer64。
需要注意的是,屬性的首字母要小寫。

關于Type類型的說明

  • Undefined: 默認值,參與編譯會報錯
  • Integer 16: 整數,表示范圍 -32768 ~ 32767
  • Integer 32: 整數,表示范圍 -2147483648 ~ 2147483647
  • Integer 64: 整數,表示范圍 –9223372036854775808 ~ 9223372036854775807
  • Float: 小數,通過MAXFLOAT宏定義來看,最大值用科學計數法表示是 0x1.fffffep+127f
  • Double: 小數,小數位比Float更精確,表示范圍更大
  • String: 字符串,用NSString表示
  • Boolean: 布爾值,用NSNumber表示
  • Date: 時間,用NSDate表示
  • Binary Data: 二進制,用NSData表示
  • Transformable: OC對象,用id表示。可以在創建托管對象類文件后,手動改為對應的OC類名。使用的前提是,這個OC對象必須遵守并實現NSCoding協議。

3.添加關聯關系

再創建一個實體Task并添加響應的屬性。

@添加關聯關系

Task添加關聯關系,點擊Relationships下面的加號,新建一個關聯關系,命名為planinverse需要設置好Relationships之后才能設置。

關聯關系設置

  • delete rule: 定義關聯屬性的刪除規則。在當前對象和其他對象有關聯關系時,當前對象被刪除后與之關聯對象的反應。這個參數有四個枚舉值,代碼對應著模型文件的相同選項。
  1. NSNoActionDeleteRule 刪除后沒有任何操作,也不會將關聯對象的關聯屬性指向nil。刪除后使用關聯對象的關聯屬性,可能會導致其他問題。
  2. NSNullifyDeleteRule 刪除后會將關聯對象的關聯屬性指向nil,這是默認值。
  3. NSCascadeDeleteRule 刪除當前對象后,會將與之關聯的對象也一并刪除。
  4. NSDenyDeleteRule 在刪除當前對象時,如果當前對象還指向其他關聯對象,則當前對象不能被刪除。
  • Type: 主要有兩種類型,To One和To Many,表示當前關系是一對多還是一對一。

4.創建托管對象類文件

創建文件
選中后綴名為.xcdatamodeld的模型文件,選擇XcodeEditor -> Create NSManagedObject Subclass -> 選擇模型文件 -> 選擇實體,生成實體對應的托管對象類文件。

@生成的文件

更新文件
當前模型對應的實體發生改變后,需要重新生成模型文件。生成步驟和上面一樣,主要是替換Category文件,托管對象文件不會被替換。生成文件時不需要刪除,直接替換文件。

增刪改查操作

1.插入操作

// 創建托管對象,并指明創建的托管對象所屬實體名
Plan *planObj = [NSEntityDescription insertNewObjectForEntityForName:@"Plan" inManagedObjectContext:context];
planObj.planName = @"計劃名字";
planObj.planId = [NSNumber numberWithInteger:1];

// 通過上下文保存對象,并在保存前判斷是否有更改
NSError *error = nil;
if (context.hasChanges) {
    [context save:&error];
}

// 錯誤處理
if (error) {
    NSLog(@"CoreData Insert Data Error : %@", error);
}

通過NSEntityDescriptioninsert類方法,生成并返回一個Employee托管對象,并將這個對象插入到指定的上下文中。
managedObjectContext將操作的數據存放在緩存層,只有調用managedObjectContextsave方法后,才會真正對數據庫進行操作,否則這個對象只是存在內存中,這樣做避免了頻繁的數據庫訪問。

2.刪除操作

// 建立獲取數據的請求對象,指明對Plan實體進行刪除操作
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plan"];

// 創建謂詞對象,過濾出符合要求的對象,也就是要刪除的對象
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"planName = %@", @"計劃名字"];
[request setPredicate:predicate];

// 執行獲取操作,找到要刪除的對象
NSError *error = nil;
NSArray<Plan *> *planArr = [context executeFetchRequest:request error:&error];

// 遍歷符合刪除要求的對象數組,執行刪除操作
[planArr enumerateObjectsUsingBlock:^(Plan * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    [context deleteObject:obj];
}];

// 保存上下文
if (context.hasChanges) {
    [context save:nil];
}

// 錯誤處理
if (error) {
    NSLog(@"CoreData Delete Data Error : %@", error);
}

3.更新操作

// 建立獲取數據的請求對象,并指明操作的實體為Plan
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plan"];

// 創建謂詞對象,設置過濾條件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"planName = %@", @"計劃名字"];
request.predicate = predicate;

// 執行獲取請求,獲取到符合要求的托管對象
NSError *error = nil;
NSArray<Plan *> *planArr = [context executeFetchRequest:request error:&error];
[planArr enumerateObjectsUsingBlock:^(Plan * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    obj.planId = @2;
}];

// 將上面的修改進行存儲
if (context.hasChanges) {
    [context save:nil];
}

// 錯誤處理
if (error) {
    NSLog(@"CoreData Update Data Error : %@", error);
}

4.查詢操作

// 建立獲取數據的請求對象,指明操作的實體為Plan
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plan"];

// 執行獲取操作,獲取所有Plan托管對象
NSError *error = nil;
NSArray<Plan *> *planArr = [context executeFetchRequest:request error:&error];
[planArr enumerateObjectsUsingBlock:^(Plan * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"Plan Name : %@, Id : %@", obj.planName, obj.planId);
}];

// 錯誤處理
if (error) {
    NSLog(@"CoreData Ergodic Data Error : %@", error);
}

小結一下

看完上面一大堆,其實應該還是不太理解。不過跟著步驟一步步走下來,應該是可以簡單實用了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容