【轉】CoreData以及MagicalRecord (一),magicalrecord
先粗略的瞭解下CoreData中的一些核心概念
1. CoreData 的核心概念
先上兩幅關鍵的概念圖
(1)NSManagedObjectModel 託管物件模型(MOM)是描述應用程式的資料模型,這個模型包含實體(Entity),特性(Property),讀取請求(FetchRequest)等。
這個MOM由實體描述對象,即NSEntityDescription
執行個體的集合組成,實體描述對象介紹見下面第7條。
作用:添加實體的屬性,建立屬性之間的關係
(2)NSManagedObjectContext 託管物件內容(MOC)參與對資料對象進行各種操作的全過程,並檢測資料對象的變化,已提供對undo/redo的支援及更新綁定至資料的UI
在概念圖2中,託管物件內容(MOC)通過持久化儲存協調器(PSC)從持久化儲存(NSPersistentStore)中擷取對象時,這些對象會形成一個臨時副本在MOC中形成一個對象集合,該對象集合包含了對象以及對象彼此之間的一些關係。我們可以對這些副本進行修改,然後進行儲存,然後MOC會通過 PSC 對 NSPersistentStore 進行操作,持久化儲存就會發生變化。
CoreData中的NSManagedObjectModel 託管對象的資料模型(MOM)
,通過 MOC 進行註冊。MOC有插入、刪除以及更新資料模型等操作,並提供了撤銷和重做的支援。
作用:插入資料,更新資料,刪除資料
(3)NSPersistentStoreCoordinator 持久化儲存協調器(PSC)相當於資料檔案管理器,處理底層的對資料檔案的讀取與寫入,一般我們無需與它打交道
在應用程式和外部資料儲存的對象之間提供訪問通道的架構對象集合統稱為持久化堆棧(persistence stack)。在堆棧頂部的是託管物件內容(MOC),在堆棧底部的是持久化Object Storage Service(persistent object stores)。在託管物件內容和持久化Object Storage Service之間便是持久化儲存協調器(PSC)。應用程式通過類NSPersistentStoreCoordinator的執行個體訪問持久化Object Storage Service。
持久化儲存協調器為一或多個託管物件內容提供一個提供者,使其下層的多個持久化儲存可以表現為單一一個彙總儲存。一個託管物件內容可以基於持久化儲存協調器下的所有資料存放區來建立一個對象圖。持久化儲存協調器只能與一個託管物件模型(MOM)相關聯。
(4)NSManagedObject 託管對象(MO)資料對象 與MOC相關聯
託管對象必須繼承自NSManagedObject
或者NSManagedObject
的子類。NSManagedObject能夠表述任何實體。它使用一個私人的內部儲存,以維護其屬性,並實現託管對象所需的所有基本行為。託管對象有一個指向實體描述的引用。NSEntityDescription 實體描述
表述了實體的中繼資料,包括實體的名稱,實體的屬性和實體之間的關係。
(5)Controller 控制器
概念圖1中綠色的 Array Controller,Object Controller,Tree Controller 這些控制器,一般都是通過 control+drag 將 Managed Object Context 綁定到它們,這樣我們就可以在 nib 中可視化地操作資料
(6)NSFetchRequest 擷取資料請求
使用託管物件內容來檢索資料時,會建立一個擷取請求(fetch request)。類似Sql查詢語句的功能。
(7)NSEntityDescription 實體描述
實體描述對象提供了一個實體的中繼資料,包括實體名(Name),類名(ClassName),屬性(Properties)以及實體屬性與其他實體的一些關係(Relationships)等。
(8).xcdatamodeld
裡面是.xcdatamodeld檔案,用資料模型編輯器編輯,編譯後為.momd或.mom檔案。
我們可以選中我們的應用程式(路徑類似為/Users/Childhood/Library/Application Support/iPhone Simulator/7.1/Applications/005D926F-5763-4305-97FE-AE55FE7281A4
),右鍵顯示包內容,我們看到是這樣的。
我們著重理解下他們之間的協同工作關係。
#pragma mark - CoreDataAbout - (void)saveContext{ NSError* error = nil; NSManagedObjectContext *managedObjectContext = self.managedObjectContext; if (managedObjectContext != nil) { if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { NSLog(@"Unresolved error :%@, %@", error, [error userInfo]); abort(); }else{ NSLog(@"save success!"); } }} - (NSURL*)applicationDocDir{ NSURL* url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]lastObject]; NSLog(@"%@", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]); return url;} // 尾碼為.xcdatamodeld的包,裡面是.xcdatamodel檔案,用資料模型編輯器編輯// 編譯後為.momd或.mom檔案- (NSManagedObjectModel*)managedObjectModel{ if (_managedObjectModel != nil) { return _managedObjectModel; } NSURL* modelURL = [[NSBundle mainBundle] URLForResource:@"Journal" withExtension:@"momd"]; NSLog(@"model url: %@", [modelURL path]); self.managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return self.managedObjectModel;} - (NSManagedObjectContext*)managedObjectContext{ if (_managedObjectContext != nil) { return _managedObjectContext; } NSPersistentStoreCoordinator* coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { self.managedObjectContext = [[NSManagedObjectContext alloc]init]; [self.managedObjectContext setPersistentStoreCoordinator:coordinator]; } return self.managedObjectContext;} - (NSPersistentStoreCoordinator*)persistentStoreCoordinator{ if (_persistentStoreCoordinator != nil) { return _persistentStoreCoordinator; } NSURL* storeUrl = [[self applicationDocDir] URLByAppendingPathComponent:@"Journal.sqlite"]; NSError* error = nil; self.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) { NSLog(@"Error: %@, %@", error, [error userInfo]); } return self.persistentStoreCoordinator;}
- 應用程式先建立或讀模數型檔案(尾碼為xcdatamodeld)產生 NSManagedObjectModel 對象。
- 產生 NSManagedObjectContext 和 NSPersistentStoreCoordinator 對象,MOC會設定自身的持久化儲存協調器(PSC),通過調用PSC來對資料檔案進行讀寫。
- NSPersistentStoreCoordinator 負責從資料檔案(xml,sqlite,二進位檔案等)中讀取資料產生 Managed Object,或儲存 Managed Object 寫入資料檔案。
- NSManagedObjectContext 參與對資料進行各種操作的整個過程,它可以持有多個 Managed Object。我們通過它來監測 Managed Object。監測資料對象有兩個作用:支援 undo/redo 以及資料繫結。這個類最常用
- Array Controller,Object Controller,Tree Controller 這些控制器一般與 NSManagedObjectContext 關聯,因此我們可以通過它們在 nib 中可視化地操作資料對象
2. Model class
模型有點像資料庫的表結構,裡麵包含 Entry, 實體又包含三種 Property:Attribute(屬性),RelationShip(關係), Fetched Property(讀取屬性)。Model class 的名字多以 "Description" 結尾。我們可以看出:模型就是描述資料類型以及其關係的。
主要的 Model class 有:
Model Classes
Managed Object Model |
NSManagedObjectModel |
資料模型 |
Entity |
NSEntityDescription |
抽象資料類型,相當於資料庫中的表 |
Property |
NSPropertyDescription |
Entity 特性,相當於資料庫表中的一列 |
> Attribute |
NSAttributeDescription |
基本數值型屬性(如Int16, BOOL, Date等類型的屬性) |
> Relationship |
NSRelationshipDescription |
屬性之間的關係 |
> Fetched Property |
NSFetchedPropertyDescription |
查詢屬性(相當於資料庫中的查詢語句) |
1)Entity - NSEntityDescription
Entity 相當於資料庫中的一個表,它描述一種抽象資料類型,其對應的類為 NSManagedObject 或其子類。
NSEntityDescription 常用方法:
+insertNewObjectForEntityForName:inManagedObjectContext: Factory 方法,根據給定的 Entity 描述,產生相應的 NSManagedObject 對象,並插入 ManagedObjectContext 中。
-managedObjectClassName 返回映射到 Entity 的 NSManagedObject 類名
-attributesByName 以名字為 key, 返回 Entity 中對應的 Attributes
-relationshipsByName 以名字為 key, 返回 Entity 中對應的 Relationships
2)Property - NSPropertyDescription
Property 為 Entity 的特性,它相當於資料庫表中的一列,或者 XML 檔案中的 value-key 對中的 key。它可以描述實體資料(Attribute),Entity之間的關係(RelationShip),或查詢屬性(Fetched Property)。
> Attribute - NSAttributeDescription
Attribute 儲存基本資料,如 NSString, NSNumber or NSDate 等。它可以有預設值,也可以使用Regex或其他條件對其值進行限定。一個屬性可以是 optional 的。
> Relationship - NSRelationshipDescription
Relationship 描述 Entity,Property 之間的關係,可以是一對一,也可以是一對多的關係。
> Fetched Property - NSFetchedPropertyDescription
Fetched Property 根據查詢謂詞返回指定 Entity 的合格資料對象。
上面說的比較抽象,舉個例子來說,見圖:
我們有一個 CocoaDataDemo.xcdatamodeld 模型檔案,應用程式根據它產生一個 NSManagedObjectModel 對象,這個模型有三個 Entity,每個 Entity 又可包含 Attribute Relationship, Feteched Property 三種類型的 Property。在本例中, Author Entity 包含兩個Attribute : name 和 email,它們對於的運行時類均為 NSManagedObject;還包含一個與 Post 的 Relationship;沒有設定 Feteched Property。
我們通常使用 KVC 機制來訪問 Property。下面來看代碼:
NSManagedObjectContext * context = [[NSApp delegate] managedObjectContext];NSManagedObject * author = nil; author = [NSEntityDescription insertNewObjectForEntityForName: @"Author" inManagedObjectContext: context];[author setValue: @"nemo@pixar.com" forKey: @"email"];NSLog (@"The Author's email is: %@", [author valueForKey:@"email"]);
在上面代碼中,我們先取得 NSManagedObjectContext, 然後調用 NSEntityDescription 的方法,以 Author 為實體模型,產生對應的 NSManagedObject 對象,插入 NSManagedObjectContext 中,然後給這個對象設定特性 email 的值。