1.原理部分
Core Data
是一個純粹的面向?qū)ο罂蚣芄北停捎糜诠芾韺嶓w以及實體之間的關(guān)聯(lián)關(guān)系的持久化曹鸠,也就是我們通常所指的數(shù)據(jù)持久化。
Core Data
底層的持久化存儲方式可以是SQLite
數(shù)據(jù)庫斥铺,也可以是XML
文檔彻桃,甚至可以直接以內(nèi)存作為持久化存儲設(shè)備。
Core Data
的核心概念是實體仅父。實體是由Core Data
管理的模型對象叛薯,它必須是NSManagedObject
類或其子類的實例。實體與實體之間存在1-1笙纤、1-N耗溜、N-N、的關(guān)聯(lián)關(guān)系省容,整個應(yīng)用的所有實體以及實體之間的關(guān)聯(lián)關(guān)系被稱為托管對象模型NSManagedObiectModel
抖拴。
Core Data
的核心對象是托管對象上下文NSManagedObjectContext
,所有實體都處于托管對象上下文管理中腥椒,Core Data
應(yīng)用對實體所做的任何增阿宅、刪、查笼蛛、改操作都必須通過托管對象上下文來完成洒放。
開發(fā)者開發(fā)的應(yīng)用程序需要通過NSMannagedObjectContext
對實體進行增、刪滨砍、查往湿、改操作,而NSMannagedObjectContext
底層與持久化存儲協(xié)調(diào)銜接惋戏,持久化存儲協(xié)調(diào)器則負責(zé)管理底層的存儲形式比如:SQLite
领追。
Core Data
應(yīng)用中的核心API
有如下幾個。
托管對象模型
NSManagedObiectModel
:該對象負責(zé)管理整個應(yīng)用的所有實體以及實體之間的關(guān)聯(lián)關(guān)系响逢。當(dāng)開發(fā)者使用Xcode
的圖形界面設(shè)計了實體與實體的關(guān)聯(lián)關(guān)系之后绒窑,需要使用該對象來加載、管理應(yīng)用的托管對象模型舔亭。
持久化存儲協(xié)調(diào)器
NSPeristentStoreCoordinator
:負責(zé)管理底層的存儲文件些膨,例如SQLite
數(shù)據(jù)庫等。
托管對象上下文
NSManagedObjectContext
:該對象是Core Data
的核心對象钦铺,應(yīng)用對實體所做的任何增订雾、刪、查职抡、改操作都必須通過該對象來完成。
實體描述
NSEntityDescription
:該對象代表了關(guān)于某個實體的描述信息误甚,從某種程度來說缚甩,該對象相當(dāng)于實體的抽象谱净。實體描述定義了該實體的名字、實體的實現(xiàn)類擅威,并用一個集合定義了該實體包含的所有屬性壕探。
抓取請求
NSFetchRequest
:該對象封裝了查詢實體的請求,包括程序需要查詢哪些實體郊丛、查詢條件李请、排序規(guī)則等。抓取請求定義了本次查詢的實體的名字厉熟、抓取請求的查詢條件导盅,通過NSPredicate來表示
,并用一個NSArray
集合定義了所有的排序規(guī)則揍瑟。
熟悉以上幾點之后白翻,使用Core Data
持久化操作的步驟大致如下。
- 創(chuàng)建
NSManagedObiectModel
對象來加載管理應(yīng)用的托管對象模型绢片。 - 以
NSManagedObiectModel
對象為基礎(chǔ)滤馍,根據(jù)實際需要創(chuàng)建NSPeristentStoreCoordinator
對象,該對象確定Core Data
底層數(shù)據(jù)的存儲形式底循。 - 以
NSManagedObiectModel
對象為基礎(chǔ)巢株,創(chuàng)建NSMannagedObjectContext
,該對象是Core Data
進行持久化訪問的核心對象熙涤。 - 對于普通的增阁苞、刪、查灭袁、改操作猬错,需要分別先創(chuàng)建實體、刪除實體茸歧、修改實體倦炒,然后調(diào)用
NSMannagedObjectContext
對象的save:
方法將這些修改保存到底層存儲設(shè)備。 - 如果要執(zhí)行查詢软瞎,則需要先創(chuàng)建
NSFetchRequest
對象逢唤,再調(diào)用NSMannagedObjectContext
的executeFetchRequest:error
:方法執(zhí)行查詢,該方法返回所有匹配條件的實體組成的NSArray
涤浇。
2.手動配置環(huán)境
iOS允許在創(chuàng)建項目時勾選“Use Core Data”復(fù)選框鳖藕,通過該方式創(chuàng)建的項目已經(jīng)完成了所有Core Data
必須資源的初始化,但此處并不打算使用這種方式來初始化Core Data
項目只锭,而是選擇從一個Empty Application
開始著恩,手動初始化Core Data
項目,這樣便于大家真正理解Core Data
項目需要初始化哪些資源。
下面我們將開始把這個Empty Application
項目一步步改造成Core Data
項目喉誊。
具體步驟如下:
為該項目添加
CoreData.framework
框架邀摆。-
為該項目添加一個實體模型文件。單擊Xcode主菜單的"File"--->"New"--->"File"菜單項伍茄,具體如下圖:
coreData01.png 在
AppDelegate
中初始化Core Data
應(yīng)用必須的核心API
對象:NSManagedObiectModel
栋盹、NSPeristentStoreCoordinator
、NSManagedObjectContext
修改應(yīng)用程序委托類的接口部分敷矫,在接口部分定義上面3個核心API
的屬性例获,并增加一個對NSManagedObjectContext
對象執(zhí)行存儲的方法、一個獲取應(yīng)用Docouments
目錄下的方法曹仗。下面是修改后的接口部分代碼榨汤。
AppDelegate.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
// 定義Core Data的3個核心API的屬性
@property (readonly, strong, nonatomic) NSManagedObjectContext*
managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator*
persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
@end
接下來在AppDelegate.m
中實現(xiàn)部分進行修改,初始化對象整葡,并實現(xiàn)saveContext
方法件余,其中applicationDocumentsDirectory
是一個非常簡單的方法,用于獲取應(yīng)用Docouments
目錄
AppDelegate.m
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// 當(dāng)應(yīng)用被中斷時候遭居,將所有托管上下文中數(shù)據(jù)保存起來
[self saveContext];
}
- (void)saveContext
{
NSError *error = nil;
// 獲取應(yīng)用的托管對象上下文
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil)
{
// 如果托管對象上下文中包含了未保存的修改啼器,執(zhí)行保存,如果保存失敗記錄錯誤信息
if ([managedObjectContext hasChanges] &&
![managedObjectContext save:&error])
{
NSLog(@"保存出現(xiàn)錯誤:%@, %@", error, [error userInfo]);
abort();
}
}
}
// 初始化應(yīng)用的托管對象上下文俱萍。
- (NSManagedObjectContext *)managedObjectContext
{
// 如果_managedObjectContext已經(jīng)被初始化過端壳,直接返回該對象
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
// 獲取持久化存儲協(xié)調(diào)器
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
// 如果持久化存儲協(xié)調(diào)器不為nil
if (coordinator != nil)
{
// 創(chuàng)建NSManagedObjectContext對象
_managedObjectContext = [[NSManagedObjectContext alloc] init];
// 為NSManagedObjectContext對象設(shè)置持久化存儲協(xié)調(diào)器
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
// 如果_managedObjectModel已經(jīng)被初始化過,直接返回該對象
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
// 獲取實體模型文件對應(yīng)的NSURL
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"FKModel"
withExtension:@"momd"];
// 加載應(yīng)用的實體模型文件枪蘑,并初始化NSManagedObjectModel對象
_managedObjectModel = [[NSManagedObjectModel alloc]
initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
// 如果_persistentStoreCoordinator已經(jīng)被初始化過损谦,直接返回該對象
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// 獲取SQLite數(shù)據(jù)庫文件的存儲目錄
NSURL *storeURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:@"Books.sqlite"];
NSError *error = nil;
// 以持久化對象模型為基礎(chǔ),創(chuàng)建NSPersistentStoreCoordinator對象
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
// 設(shè)置持久化存儲協(xié)調(diào)器底層采用SQLite存儲機制岳颇,如果設(shè)置失敗記錄錯誤信息
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:nil error:&error])
{
NSLog(@"設(shè)置持久化存儲失斦占瘛:%@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
// 獲取應(yīng)用的Documents目錄
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
}
到此Core Data
所依賴的環(huán)境基本上已經(jīng)搭建完畢,應(yīng)用執(zhí)行增话侧、刪栗精、查、改操作直接調(diào)用managedObjectContext
方法即可操作瞻鹏。
3.設(shè)計實體模型
Xcode中找到我們創(chuàng)建的Core Data
文件悲立,打開實體模型開始編輯,具體如下圖:
下面我們添加一個簡單的實體新博,點擊上圖走下角的Add Entity
薪夕,系統(tǒng)將會在ENTITIES
列表下添加一個實體,將該實體重命名為項目所需的名字赫悄,此處為Bison
PS長按Add Entity
將會顯示Add Entity
原献、Add Fetch Request
馏慨、Add Configuration
列表,可供選擇添加實體姑隅、抓取請求熏纯、配置。
選中Bison
實體粤策,通過點擊上圖右下角的Add Attribute
按鈕,系統(tǒng)將會為該Bison
實體添加一個屬性误窖,將該屬性重命名所需的名字叮盘,此處重命名name
,并為該屬性選擇類型霹俺,在此選String
類型,注意:此處命名首字母不能大寫哦柔吼。
PS長按Add Attribute
將會顯示Add Attribute
、Add Relationship
丙唧、Add Configuration
愈魏、Add Fetch Property列表,可供選擇添加屬性想际、關(guān)聯(lián)關(guān)系培漏、抓取屬性,也可以通過 +
胡本、—
來添加與刪除牌柄。
重復(fù)上面的操作增加一個birthDay
的屬性,改屬性為date
類型侧甫。實體設(shè)計完后珊佣,如下圖:
然后單擊Xcode主菜單的Editor
-->Create NSManagedObject Subclass
菜單項,如果系統(tǒng)包含倆個以上的實體披粟,Xcode將會彈出一個對話框讓選擇腰圍哪些實體生成NSManagedObject
的子類咒锻,然后彈出對話框讓選擇NSManagedObject
的子類的存儲路徑。選完之后Create
按鈕即可守屉。
經(jīng)過上面的操作惑艇,為實體模型添加一個簡單的Bison
實體,該實體包含倆個屬性胸梆,單不包含任何關(guān)聯(lián)關(guān)系敦捧。
4.Core Data
數(shù)據(jù)的增刪查改
獲取托管對象上下文NSManagedObjectContext
之后,接下來即可通過該對象來執(zhí)行增碰镜、刪兢卵、查、改操作绪颖。
- 添加實體
添加實體的步驟如下:
調(diào)用NSEntityDescription
的insertNewObjectForEntityForName:inManagedObjectContext:
靜態(tài)方法添加新實體秽荤。該方法的第1個參數(shù)為實體名甜奄,第2個參數(shù)為NSManagedObjectContext
對象。為新實體設(shè)置屬性窃款。調(diào)用NSManagedObjectContext
對象的save:
方法執(zhí)行保存课兄。如下代碼片段:
// 控制Core Data在托管對象上下文中創(chuàng)建一個新實體
Bison* bison = [NSEntityDescription
insertNewObjectForEntityForName:@"Bison"
inManagedObjectContext:self.appDelegate.managedObjectContext];
// 為新實體設(shè)置屬性
bison.name = @"linbin";
bison.birth_Day = [NSDate date];
// 定義一個NSError對象,用于接受錯誤信息
NSError *error;
// 設(shè)置完實體屬性之后晨继,調(diào)用托管對象上下文的`save:`方法將實體寫入數(shù)據(jù)庫烟阐,如果保存成功
if ([self.appDelegate.managedObjectContext save:&error])
{
[[[UIActionSheet alloc] initWithTitle:@"保存成功" delegate:nil
cancelButtonTitle:@"確定" destructiveButtonTitle:nil
otherButtonTitles: nil] showInView:self.view];
}
else
{
NSLog(@"保存FKEvent實體出錯: %@,%@" , error ,[error userInfo]);
}
- 刪除實體
刪除實體的步驟如下:
首先獲取要刪除的實體,然后調(diào)用NSManagedObjectContext
對象的deleteObject:
方法刪除實體紊扬。最后調(diào)用NSManagedObjectContext
對象的save:
方法執(zhí)行保存蜒茄。如下代碼:
// 獲取將要刪除的實體
Bison* deleteEvent = .....;
// 從托管對象上下文中刪除指定對象
[self.appDelegate.managedObjectContext deleteObject:deleteEvent];
NSError *error;
// 保存刪除操作,如果出現(xiàn)錯誤餐屎,顯示錯誤信息
if (![self.appDelegate.managedObjectContext save:&error])
{
NSLog(@"刪除FKEvent實體出錯:%@,%@",error,[error userInfo]);
}
- 修改實體
修改實體的步驟如下:
首先獲取要修改的實體檀葛,必須處于NSManagedObjectContext
管理下的實體;然后修改實體的屬性腹缩;再調(diào)用NSManagedObjectContext
對象的save:
方法執(zhí)行保存屿聋。如下代碼:
// 獲取將要修改的實體
Bison* updateEvent = .....;
//修改實體的屬性
.....
//定義一個NSError對象,用于接收錯誤信息
NSError *error;
// 保存修改操作藏鹊,如果出現(xiàn)錯誤润讥,顯示錯誤信息
if (![self.appDelegate.managedObjectContext save:&error])
{
NSLog(@"刪除FKEvent實體出錯:%@,%@",error,[error userInfo]);
}
- 查詢實體
查詢實體的步驟如下:
首先創(chuàng)建NSFetchRequest
對象。然后通過NSEntityDescription
對象設(shè)置NSFetchRequest
對象將要抓取的實體盘寡。如果需要對抓取結(jié)果進行篩選象对,則需要通過NSPredicate
對象設(shè)置篩選條件。如果需要對結(jié)果進行排序宴抚,還需要為NSFetchRequest
添加多個NSSortDescriptor
對象勒魔。再調(diào)用NSManagedObjectContext
對象的executeFetchRequest:error:
方法執(zhí)行查詢,該查詢方法將會返回所有符合條件的實體組成的NSArray
集合菇曲。如下代碼:
// 創(chuàng)建抓取數(shù)據(jù)的請求對象
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// 設(shè)置要抓取哪種類型的實體
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Bison"
inManagedObjectContext:self.appDelegate.managedObjectContext];
// 設(shè)置抓取實體
[request setEntity:entity];
NSError *error = nil;
// 執(zhí)行抓取數(shù)據(jù)的請求冠绢,返回符合條件的數(shù)據(jù)
eventArray = [[self.appDelegate.managedObjectContext
executeFetchRequest:request error:&error] mutableCopy];
基本的方法到此就結(jié)束了,具體的詳情可以下載Demo查看
下載地址
好文推薦:仿window阿里旺旺登陸界面,打印機吐紙動畫效果
原文地址:http://allluckly.cn
如對你有幫助常潮,請不要吝惜你的star和喜歡哦弟胀!
技術(shù)交流群:534926022(免費) 511040024(0.8/人付費)
版權(quán)歸?Bison所有 如需轉(zhuǎn)載請保留原文超鏈接地址!否則后果自負喊式!