Just a Computer Graphics Studio & My Life

[iOS] Core Data 基礎概念

維基百科這麼介紹Core Data

簡單的說,Core Data就是可以儲存到磁碟的物件圖,Core Data可以幫我們做很多工作,它可以作為軟體的整個模型層。它不僅僅在磁碟上儲存資料,也把我們需要的資料物件讀取到記憶體中。—Marcus Zarra,Core Data

Core Data是Mac OS X中Cocoa API的一部分,首次在Mac OS X 10.4 Tiger與iOS 3.0系統中出現。它允許按照實體-屬性-值 (EAV)模型組織資料,並以XML、二進制檔案或SQLite資料檔案的格式將其序列化。Core Data允許使用者使用代表實體和實體間關聯的高層物件來運算元據。它也可以管理序列化的資料,提供物件生存期管理與object graph管理,包括儲存。Core Data直接與SQLite互動,避免開發者使用原本較複雜的SQL語句。

就像Cocoa繫結在模型-檢視-控制器 (MVC)設計中做了很多控制器的工作一樣,Core Data做了很多資料模型的工作。它的主要任務是負責資料更改的管理,序列化到磁碟,最小化記憶體佔用,以及查詢資料。

Core Data是在iPhone OS 3.0後所新增的功能,是高階抽象化的物件儲存管理系統,我們可以使用NSPredicate和NSEntityDescription兩個類別來代替複雜的SQL指令。

詳細的使用方式可以參考Apple開發者文件:Core Data Tutorial for iPhone OS

若說SQLite適合用在已存在資料庫的存取,那麼Core Data就更適合在程式執行時所產生資料的存取,它把資料儲存的方式、資料處理的語法抽離出來。

core data

Core Data模型

  1. Managed Object Model 
    Managed Object Model是描述應用程序的資料模型,這個模型包含實體(Entity),特性(Property),讀取請求(Fetch Request )等。
  2. Managed Object Context
    Managed Object Context參與對數據對象進行各種操作的全過程,並監測資料對象的變化,以提供對undo/redo的支持及更新綁定到資料的UI。
  3. Persistent Store Coordinator
    Persistent Store Coordinator相當於資料文件管理器,處理底層的對資料文件的讀取與寫入。一般我們無需與它打交道。
  4. Managed Object
    Managed Object資料對象,與Managed Object Context相關聯。
  5. Controller
    圖中綠色的Array Controller、Object Controller、Tree Controller這些控制器,一般都是通過control+drag將Managed Object Context綁定到它們,這樣我們就可以在nib中可視化地操作資料。
core data process

Core Data運作

  1. 應用程序先創建或讀取模型文件(後綴為xcdatamodeld)生成NSManagedObjectModel對象。Document應用程序是一般是通過NSDocument或其子類NSPersistentDocument)從模型文件(後綴為xcdatamodeld)讀取。
  2. 然後生成NSManagedObjectContext和NSPersistentStoreCoordinator對象,前者對用戶透明地調用後者對資料文件進行讀寫。
  3. NSPersistentStoreCoordinator負責從資料文件(xml、sqlite、二進製文件等)中讀取資料生成Managed Object,或保存Managed Object寫入數據文件。
  4. NSManagedObjectContext參與對資料進行各種操作的整個過程,它持有Managed Object。我們通過它來監測Managed Object。監測資料對象有兩個作用:支持undo/redo以及資料綁定。這個類是最常被用到的。
  5. Array Controller、Object Controller、Tree Controller這些控制器一般與NSManagedObjectContext關聯,因此我們可以通過它們在nib中可視化地操作資料對象。

基本術語.類別名稱

  • 表結構:NSEntityDescription (實體描述)
  • 表記錄:NSManagedObject (受托管的物件)
  • 資料庫存取:NSPersistentStoreCoordinator (檔案儲存協調器)
  • 資料庫操作:NSManagedObjectContext (受托管的物件文本)

Managed Object Context這類別記載了我們的App在記憶體中所有的Entity,當你要求Core Data載入物件時,你必須先向Managed Object Context提出要求。

假如Entity不存在記憶體中的話,Managed Object Context會向Persistent Store Coordinator發出請求,試著嘗試尋找它。

Persistent Store Coordinator的任務是追蹤Persistent Object Store,而Persistent Object Store實際知道如何讀寫資料。

Managed Object Model則是用來處理資料,這些元件都知道要如何處理資料。

資料庫與Core Data的對應

  • 資料表 (Table) vs 實體 (Entity)
  • 欄位 (Field) vs 屬性 (Attribute)
  • 表格間的關聯 vs 關係 (Relationship)

Core Data與資料庫之間雖然有很類似的關係存在,然而Core Data允許你將資料以其它的檔案類型來儲存,例如:XML。這是因為在Core Data的架構上存在一個檔案儲存協調器 (Persistent store coordinator),當Core Data要存取後端的檔案系統的時候,就是透過它來進行讀寫的動作。為了方便存取Entity以及透過檔案儲存協調器來存取檔案系統,Core Data提供一個受托管的物件文本 (Managed object context)的物件來作為窗口。

類別名稱.用途.關鍵方法

類別名稱 用途 關鍵方法
NSManagedObject
  • 資料物件
  • 管理屬性
  • -entity
  • -valueForKey:
  • -setValue: forKey:
NSManagedObjectContext
  • 資料庫
  • 獲取與儲存
  • -executeFetchRequest: error:
  • -save
NSManagedObjectModel
  • 資料模型
  • -entities
  • -fetchRequestTemplateForName:
  • -setFetchRequestTemplate: forName:
NSFetchRequest
  • 請求資料
  • -setEntity:
  • -setPredicate:
  • -setFetchBatchSize:
NSPersistentStoreCoordinator
  • 中介
  • 儲存資料
  • -addPersistentStoreWithType: configuration: URL: options: error:
  • -persistentStoreForURL:
NSPredicate
  • 確定查詢條件
  • +predicateWithFormat:
  • -evaluateWithObject:

簡單專案展示

建立一個專案,專案模板基於「Master-Detail Application」,點擊「Next」按鈕,專案命名為「CoreDataDemo」,並勾選「Use Core Data」,點擊「Next」,選擇專案存放的目錄,點擊「Create 」按鈕,專案建立完畢。

程式碼

AppDelegate.h定義了三個property

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

AppDelegate.m實作三個對應的回傳

#pragma mark - Core Data stack
- (NSManagedObjectContext *)managedObjectContext
{
...
 return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
...
 return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
...
 return _persistentStoreCoordinator;
}

仔細分析那三個方法的實作,可發現生成物件的順序為:

  1. NSManagedObjectModel
  2. NSPersistentStoreCoordinator
  3. NSManagedObjectContext

於是乎之後我們只要操作NSManagedObjectContext即可!

以上三個方法中有兩個檔案名稱:

  1. CoreDataDemo.sqlite:連結檔案系統,所有Entity最終會被儲存在這個SQLite資料庫檔案內。
  2. CoreDataDemo.momd:儲存物件模型的檔案。

在專案中找不到上述兩個檔案,原因在於它們都是在編譯過後才產生的檔案,其中CoreDataDemo.momd是編譯後的物件模型,其原始檔為CoreDataDemo.xcdatamodel。

MasterViewController.m

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.title = NSLocalizedString(@"Master", @"Master");
        id delegate = [[UIApplication sharedApplication] delegate];
        self.managedObjectContext = [delegate managedObjectContext];
    }
    return self;
}

這些對象在哪裡被調用的呢?在初始化函數中,我們看到透過獲取delegate,再透過delegate調用方法managedObjectContext,如此就得到了這個NSManagedObjectContext對象,NSManagedObjectContext對象它會跟NSPersistentStoreCoordinator對象打交道,NSPersistentStoreCoordinator會去處理底層的存儲方式。

最後是從fetchedResultsController這個method獲取到查詢結果:

FetchedResultsController *)fetchedResultsController
{
// 如果查詢結果已經存在就直接返回_fetchedResultsController
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}

// 1.創建NSFetchRequest對象(相當於SQL語句)
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

// 2.創建查詢實體(相當於設置查詢哪個表)
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

// 設置獲取數據的批數
[fetchRequest setFetchBatchSize:20];

// 3.創建排序描述符(ascending:是否升序)
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

[fetchRequest setSortDescriptors:sortDescriptors];

// 根據fetchRequest和managedObjectContext來創建aFetchedResultsController對象,並設置緩存名字為"Master"
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];

// 設置aFetchedResultsController的委託對象為當前類
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

NSError *error = nil;
// 獲取第一批數據
if (![self.fetchedResultsController performFetch:&error])
{
// 錯誤處理
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}

return _fetchedResultsController;
}

模型定義圖示

CoreDataDemo.xcdatamodeld

coredata graph

Core Data Graph

coredata table

Core Data Table

模擬器執行

coredata demo

Core Data的概念實在博大精深,若能先懂SQLite的話,就更能體會Core Data給予的好處,之後還有繼續瞭解新增、刪除和修改,然後是篩選資料~也只有在實際操作過後,才能真正瞭解Core Data的威能。

參考:

廣告

發表留言

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

標籤雲

%d 位部落客按了讚: