一、何為CoreData
CoreData是一個專門用來管理資料的架構,其在效能與書寫方便上都有很大的優勢,在資料庫管理方面,apple強烈推薦開發人員使用CoreData架構,在apple的官方文檔中稱,使用CoreData架構可以減少開發人員50%——70%的代碼量,這雖然有些誇張,但由此可見,CoreData的確十分強大。
二、設計資料模型
在iOS開發中,時常使用SQL資料庫對大量的表結構資料進行處理,但是SQL有一個十分明顯的缺陷,對於常規資料模型的表,其處理起來是沒問題的,例如一個班級表,其中每條資料中有班級名稱,人數這樣的屬性,一個學生表,其中每條資料有學生的姓名,性別,年齡這樣的屬性。但是如果要在表與表之間建立聯絡,自訂對象與自訂對象之間產生從屬關係,使用SQL處理起來就十分麻煩了,例如如果這個班級表中有一個班長的屬性,這個屬性是一個學生類型。
1.建立實體類型及其屬性
使用Xcode建立一個工程,在工程中建立一個檔案,選擇Core Data分類中的DataModel建立,如下圖:
這時在Xcode的檔案導航區會出現一個以xcdatamodeld為副檔名的檔案,這個檔案就是資料模型檔案,點擊Add Entity按鈕添加一個實體類型,取名為SchoolClass,為這個類型添加兩個屬性,分別為名字name和學生數量stuNum,如下圖:
2.對實體類型進行設定
在Xcode右側的工具列中可以對實體類型進行一些設定,選中一個實體類型,如下圖:
Name設定實體類型的名稱,Abstract Entity設定是否是抽象實體,如果勾選,則此實體不能被執行個體化,只能被繼承,類似於抽象類別,比如定義人為一個實體類型,在定義繼承於人實體類型的老師、學生等來進行執行個體化。Parent Entity用來選擇父類實體,Class用於設定對應的類的。
3.在實體物件之間建立關係
再建立一個學生類實體Student,添加name和age兩個屬性。選中SchoolClass,在其中的Relationships模組中點擊+號,來添加一個關係,如下圖:
這時,SchoolClass實體類型中就有了一個Student類型的班長屬性。如果切換一下編輯風格,可以更加清晰的看到實體類型之間的關係,如下圖:
4.對屬性和關係進行設定
選中一個屬性或者關係,在右側的工具列中可以對屬性進行一些設定,如下圖:
name設定屬性的名字,Optional類型代表可選,即在執行個體化對象時可以賦值也可以不賦值。Attribute設定屬性的資料類型,Default Value設定資料的預設值。
二、資料模型管理類NSManagedObjectModel
通過NSManagedObjectModel,可以將建立的資料模型檔案讀取為模型管理類對象,使用如下方法:
//擷取.xcdatamodeld檔案url
NSURL *modelUrl = [[NSBundle mainBundle]URLForResource:@"Model" withExtension:@"momd"];
//讀取檔案
NSManagedObjectModel * mom = [[NSManagedObjectModel alloc]initWithContentsOfURL:modelUrl];
其中還有一些屬性和方法進行資料模型的管理:
//將多個資料模型管理檔案進行合并
+ (nullable NSManagedObjectModel *)mergedModelFromBundles:(nullable NSArray<NSBundle *> *)bundles;
//將多個資料模型管理類對象進行合并
+ (nullable NSManagedObjectModel *)modelByMergingModels:(nullable NSArray<NSManagedObjectModel *> *)models;
//存放資料中所有實體模型的字典 字典中是實體名和實體描述對象
@property (readonly, copy) NSDictionary<NSString *, NSEntityDescription *> *entitiesByName;
//存放資料中所有實體描述對象
@property (strong) NSArray<NSEntityDescription *> *entities;
//返回所有可用的配置名稱
@property (readonly, strong) NSArray<NSString *> *configurations;
//擷取關聯某個配置的所有實體
- (nullable NSArray<NSEntityDescription *> *)entitiesForConfiguration:(nullable NSString *)configuration;
//為某個實體關聯配置
- (void)setEntities:(NSArray<NSEntityDescription *> *)entities forConfiguration:(NSString *)configuration;
//建立請求模板
- (void)setFetchRequestTemplate:(nullable NSFetchRequest *)fetchRequestTemplate forName:(NSString *)name;
//擷取請求模板
- (nullable NSFetchRequest *)fetchRequestTemplateForName:(NSString *)name;
關於實體描述對象NSEntityDescription:
實體類似於資料庫中的表結構,例如上次我們建立的班級實體模型,一個實體模型中可以添加許多屬性與關係,NSEntityDescription對象中存放這些資訊,常用如下:
//實體所在的模型管理對象
@property (readonly, assign) NSManagedObjectModel *managedObjectModel;
//實體所在的模型管理對象的名稱
@property (null_resettable, copy) NSString *managedObjectClassName;
//實體名
@property (nullable, copy) NSString *name;
//設定是否是抽象實體
@property (getter=isAbstract) BOOL abstract;
//子類實體字典
@property (readonly, copy) NSDictionary<NSString *, NSEntityDescription *> *subentitiesByName;
//所有子類實體物件數組
@property (strong) NSArray<NSEntityDescription *> *subentities;
//父類實體
@property (nullable, readonly, assign) NSEntityDescription *superentity;
//所有屬性字典
@property (readonly, copy) NSDictionary<NSString *, __kindof NSPropertyDescription *> *propertiesByName;
//所有屬性數組
@property (strong) NSArray<__kindof NSPropertyDescription *> *properties;
//所有常類型屬性
@property (readonly, copy) NSDictionary<NSString *, NSAttributeDescription *> *attributesByName;
//所有關係
@property (readonly, copy) NSDictionary<NSString *, NSRelationshipDescription *> *relationshipsByName;
//某個實體類型的所有關係
- (NSArray<NSRelationshipDescription *> *)relationshipsWithDestinationEntity:(NSEntityDescription *)entity;
//判斷是否是某種實體
- (BOOL)isKindOfEntity:(NSEntityDescription *)entity;
NSPropertyDescription類是資料模型屬性的父類,NSAttributeDescription和NSRelationshipDescription都是繼承於NSPropertyDescription類,NSAttributeDescription描述正常類型的屬性,NSRelationshipDescription用於描述自訂類型的關係。
三、持久化儲存協調者類NSPersistentStoreCoordinator
NSPersistentStoreCoordinator建立資料模型與本地檔案或資料庫之間的聯絡,通過它將本機資料讀入記憶體或者將修改過的臨時資料進行持久化的儲存。其初始化與連結資料持久化接收對象方法如下:
//通過資料模型管理對象進行初始化
- (instancetype)initWithManagedObjectModel:(NSManagedObjectModel *)model;
//添加一個持久化的資料接收對象
- (nullable __kindof NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType configuration:(nullable NSString *)configuration URL:(nullable NSURL *)storeURL options:(nullable NSDictionary *)options error:(NSError **)error;
//移除一個持久化的資料接收對象
- (BOOL)removePersistentStore:(NSPersistentStore *)store error:(NSError **)error;
四、資料對象管理上下文NSManagedObjectContext
NSManagedObjectContext是進行資料管理的核心類,我們通過這個類來進行資料的增刪改查等操作。其中常用方法如下:
//初始化方法 通過一個並發類型進行初始化 參數枚舉如下:
/*
typedef NS_ENUM(NSUInteger, NSManagedObjectContextConcurrencyType) {
NSPrivateQueueConcurrencyType = 0x01,//內容物件與私人隊列關聯
NSMainQueueConcurrencyType = 0x02//內容物件與主隊列關聯
};
*/
- (instancetype)initWithConcurrencyType:(NSManagedObjectContextConcurrencyType)ct;
//非同步執行block
- (void)performBlock:(void (^)())block;
//同步執行block
- (void)performBlockAndWait:(void (^)())block;
//關聯資料持久化對象
@property (nullable, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
//是否有未認可的變更
@property (nonatomic, readonly) BOOL hasChanges;
//進行查詢資料請求
- (nullable NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error;
//進行查詢資料條數請求
- (NSUInteger) countForFetchRequest: (NSFetchRequest *)request error: (NSError **)error ;
//插入元素
- (void)insertObject:(NSManagedObject *)object;
//刪除元素
- (void)deleteObject:(NSManagedObject *)object;
//復原一步操作
- (void)undo;
//清楚緩衝
- (void)reset;
//還原資料
- (void)rollback;
//提交儲存資料
- (BOOL)save:(NSError **)error;