OC有多種數(shù)據(jù)持久化得方式
Write寫(xiě)入方式(nsstring,data,nsdictionary,nsarray)
preference(偏好設(shè)置,NSUserDefaults,屬性)(nsstring,nsnumber,nsdata,nsdate,nsarray,nsdictionary)
NSKeyedArchiver(歸檔,用的不多)
SQLite 3 (需要導(dǎo)入庫(kù)libsqlite3.0.tbd,并且在使用時(shí)要包含
頭文件)
CoreData (IOS5后出的框架,能幫助我們不寫(xiě)SQL語(yǔ)句將數(shù)據(jù)保存在SQLite數(shù)據(jù)庫(kù)文件中,并對(duì)數(shù)據(jù)進(jìn)行管理)
下面看看coreData的使用方法
1.新建一個(gè)工程
(1)先不勾選Xcode為我們提供的Use Core Data,自己通過(guò)代碼創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)

(2)進(jìn)到工程后新建文件,選擇iOS->CoreData->Data Model,給這個(gè)Data Model取一個(gè)名字,保存


(3)創(chuàng)建好后工程中多出Model.xcdatamodeld文件,我們可以對(duì)這個(gè)文件進(jìn)行操作
(4)左下角有Add Entity按鈕,添加一個(gè)實(shí)體(相當(dāng)于數(shù)據(jù)庫(kù)中的表)。添加一個(gè)Entity,取名為Person

(5)選中Person,點(diǎn)擊右下角Add Attribute 或右邊Attribute欄目中點(diǎn)擊加號(hào),
為Person添加屬性(我添加了name,age兩個(gè)屬性,設(shè)置其類(lèi)型為string和integer16類(lèi)型)

2.做好上述操作后到AppDelegate.m文件中寫(xiě)寫(xiě)創(chuàng)建代碼,記得包含 頭文件;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
這個(gè)方法在程序加載完成后會(huì)調(diào)用
3.代碼創(chuàng)建SQLite數(shù)據(jù)庫(kù)
先理解幾個(gè)概念:
1.NSManagedObjectContext(負(fù)責(zé)應(yīng)用和數(shù)據(jù)庫(kù)的交互,所有對(duì)數(shù)據(jù)庫(kù)的操作都是通過(guò)它來(lái)完成的)
NSManagedObjectContext擁有一個(gè)NSPersistentStoreCoordinator類(lèi)的實(shí)例對(duì)象
2.NSPersistentStoreCoordinator(用來(lái)添加持久化存儲(chǔ)庫(kù),這里是SQLite數(shù)據(jù)庫(kù))
NSPersistentStoreCoordinator擁有一個(gè) NSManagedObjectModel類(lèi)的實(shí)例對(duì)象
3. NSManagedObjectModel(CoreData的模型文件,本例中就是上面創(chuàng)建Model.xcdatamodeld的模型)
NSManagedObjectModel有entities(數(shù)組)這個(gè)屬性(本例中就是指Person,因?yàn)橹粍?chuàng)建了Person這一個(gè)實(shí)體,所以數(shù)組中就只有這一個(gè)元素)
4.NSManagedObject(對(duì)象模型,例如下面代碼中要新建的personOne)
5.NSEntityDescription(用來(lái)描述實(shí)體)想要添加到數(shù)據(jù)庫(kù)的模型不能用alloc init 來(lái)創(chuàng)建,只能用NSEntityDescription來(lái)描述
//構(gòu)建路徑,獲取到沙盒里的Documents路徑
NSURL*documentURL = [[[NSFileManagerdefaultManager] URLsForDirectory:NSDocumentDirectoryinDomains:NSUserDomainMask] lastObject];
//打印沙盒路徑,方便后面查看
NSLog(@"%@",documentURL);
//經(jīng)過(guò)編譯后數(shù)據(jù)模型文件的擴(kuò)展名由xcdatamodeld變成了momd
NSURL*modelURL = [[NSBundlemainBundle] URLForResource:@"Model"withExtension:@"momd"];
//構(gòu)建CoreData的模型文件,就是Model.xcdatamodeld的模型
NSManagedObjectModel*managedModel = [[NSManagedObjectModelalloc] initWithContentsOfURL:modelURL];
//通過(guò)模型文件創(chuàng)建PersistentStoreCoordinator對(duì)象,
NSPersistentStoreCoordinator*persistStore = [[NSPersistentStoreCoordinatoralloc] initWithManagedObjectModel:managedModel];
//構(gòu)造數(shù)據(jù)庫(kù)存儲(chǔ)路徑URL
NSURL*persistStoreURL = [documentURL URLByAppendingPathComponent:@"Model.sqlite"];
//設(shè)置persistStore的持久化存儲(chǔ)方式為SQLiteStoreType,代表persistStore會(huì)自動(dòng)生成一個(gè)SQLite數(shù)據(jù)庫(kù)文件來(lái)實(shí)現(xiàn)持久化存儲(chǔ),并會(huì)自動(dòng)生成SQL語(yǔ)句來(lái)做CRUD(增刪改查)
[persistStore addPersistentStoreWithType:NSSQLiteStoreTypeconfiguration:nilURL:persistStoreURL options:nilerror:nil];
//NSManagedObjectContext:所有的ManagedObject的CRUD都是在context上進(jìn)行的。
//NSMainQueueConcurrencyType:這個(gè)context所關(guān)聯(lián)的控制器和UI控件只能在主線(xiàn)程中使用
NSManagedObjectContext*managerContext = [[NSManagedObjectContextalloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
//建立persistStore和context的關(guān)聯(lián)
[managerContext setPersistentStoreCoordinator:persistStore];
//創(chuàng)建需要保存的對(duì)象personOne
NSManagedObject*personOne = [NSEntityDescriptioninsertNewObjectForEntityForName:@"Person"inManagedObjectContext:managerContext];
//設(shè)置personOne的屬性,這里personOne和我們平常用的person實(shí)例有一點(diǎn)區(qū)別,它無(wú)法通過(guò)點(diǎn)語(yǔ)法直接拿到屬性(后面有解決方法),只能通過(guò)KVC來(lái)設(shè)置它的屬性
[personOne setValue:@23forKey:@"age"];
[personOne setValue:@"wl"forKey:@"name"];
//保存數(shù)據(jù)
if([managerContext save:nil])
{
NSLog(@"保存數(shù)據(jù)成功");
}
4.運(yùn)行,可以看到如下打印結(jié)果

5.復(fù)制路徑去沙盒里查看,注意復(fù)制的時(shí)候路徑的正確性,去掉前面的file://

6.可以看到數(shù)據(jù)庫(kù)已經(jīng)創(chuàng)建成功,打開(kāi)數(shù)據(jù)庫(kù)可以看到數(shù)據(jù)也已經(jīng)成功添加了(SQLiteManager)

7.上面已經(jīng)完成了簡(jiǎn)單的數(shù)據(jù)庫(kù)創(chuàng)建,然而還是有一些問(wèn)題
顯然personOne的屬性通過(guò)KVC的方式設(shè)置不太好,解決:我們可以自己創(chuàng)建Person類(lèi)來(lái)設(shè)置屬性,CoreData為我們提供了一種簡(jiǎn)單的方法
3.接下來(lái)就是與Xcode 7 以及以前版本不同的地方了,創(chuàng)建NSManagedObject SubClass文件
xcode8新版本
選中Person 這個(gè)Entity,在頂部狀態(tài)欄中點(diǎn)擊創(chuàng)建,特別注意:默認(rèn)創(chuàng)建的是swift,如果要?jiǎng)?chuàng)建OC的,需要修改一下語(yǔ)言選擇


ToosVersion最好選擇8.0,當(dāng)然,選擇7.3也是沒(méi)有問(wèn)題的,創(chuàng)建會(huì)出現(xiàn)四個(gè)文件,如圖所示:

xcode7老版本 ?command+n,選擇iOS->CoreData->NSmanagerObject subclass

8.next->勾選上dataModel-> next->勾選上Person創(chuàng)建,系統(tǒng)會(huì)幫我們自動(dòng)生成4個(gè)文件

9.在AppDelegate.m中導(dǎo)入Person.h并修改代碼managerObject 部分代碼
修改前部分
//創(chuàng)建需要保存的對(duì)象personOne
NSManagedObject*personOne = [NSEntityDescriptioninsertNewObjectForEntityForName:@"Person"inManagedObjectContext:managerContext];
//設(shè)置personOne的屬性,這里personOne和我們平常用的person實(shí)例有一點(diǎn)區(qū)別,它無(wú)法通過(guò)點(diǎn)語(yǔ)法直接拿到屬性(后面有解決方法),只能通過(guò)KVC來(lái)設(shè)置它的屬性
[personOne setValue:@23forKey:@"age"];
[personOne setValue:@"wl"forKey:@"name"];
這部分替換成
Person *personTwo = [NSEntityDescriptioninsertNewObjectForEntityForName:@"Person"inManagedObjectContext:managerContext];
personTwo.age =@100;
personTwo.name = @"lw";
10.運(yùn)行,查看數(shù)據(jù)庫(kù),數(shù)據(jù)也成功添加進(jìn)去了

也許你沒(méi)有那么順利:報(bào)錯(cuò)了:
發(fā)現(xiàn)報(bào)錯(cuò)了,錯(cuò)誤原因如下

我們?cè)谧钣覀?cè)的菜單欄中,將Codegen改為Manrual/None

這里,如果還是報(bào)錯(cuò),請(qǐng)將identity and type改為Core Data Model

并且將Class中的codege設(shè)置成Manua/None

Clean 完后 跑一下發(fā)現(xiàn)正常運(yùn)行,到此,就配置完畢了。
11.知道了整個(gè)過(guò)程后現(xiàn)在再新建一個(gè)工程看系統(tǒng)是勾選Use Core Data看看Xcode是如何實(shí)現(xiàn)的

(1)AppDelegate.h ?多出了3個(gè)屬性和2個(gè)方法,AppDelegate.m是實(shí)現(xiàn)過(guò)程(就不放上來(lái)了,可以自己新建一個(gè)工程看,思路是一致的,考慮的更全面,
熟悉過(guò)程后創(chuàng)建可以直接copy系統(tǒng)的實(shí)現(xiàn)代碼。
@property(readonly, strong,nonatomic)NSManagedObjectContext*managedObjectContext;
@property(readonly, strong,nonatomic)NSManagedObjectModel*managedObjectModel;
@property(readonly, strong,nonatomic)NSPersistentStoreCoordinator*persistentStoreCoordinator;
- (void)saveContext;
- (NSURL*)applicationDocumentsDirectory;