在iOS開發(fā)過程中,不管是做什么應(yīng)用琴许,都會(huì)碰到數(shù)據(jù)存儲(chǔ)的問題。將數(shù)據(jù)存儲(chǔ)到本地溉躲,能夠讓程序的運(yùn)行更加流暢榜田,不會(huì)出現(xiàn)讓人厭煩的菊花,使得用戶體驗(yàn)更好锻梳。下面介紹一下數(shù)據(jù)保存的方式:
1.Write寫入方式:永久保存在磁盤中箭券。具體方法為:
第一步:獲得文件即將保存的路徑:
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);//使用C函數(shù)NSSearchPathForDirectoriesInDomains來獲得沙盒中目錄的全路徑。該函數(shù)有三個(gè)參數(shù),其中布爾值表示是否需要通過~擴(kuò)展路徑疑枯。
還有一種方法是使用NSHomeDirectory函數(shù)獲得sandbox的路徑:
NSHomeDirectory();// Once you have the full sandbox path, you can create a path from it辩块,但是不能在sandbox的本文件層上寫文件也不能創(chuàng)建目錄,而應(yīng)該是此基礎(chǔ)上創(chuàng)建一個(gè)新的可寫的目錄荆永,例如Documents,Library或者temp废亭。NSString *documentPath = [sandboxPath stringByAppendingPathComponent:@"Documents"];//將Documents添加到sandbox路徑上,具體原因前面分析了具钥!
這兩者的區(qū)別就是:使用NSSearchPathForDirectoriesInDomains比在NSHomeDirectory后面添加Document更加安全豆村。因?yàn)樵撐募夸浛赡茉谖磥戆l(fā)送的系統(tǒng)上發(fā)生改變。
第二步:生成在該路徑下的文件:
[documentDirectory stringByAppendingPathComponent:fileName];//fileName就是保存文件的文件名
第三步:往文件中寫入數(shù)據(jù):
[data writeToFile:FileName atomically:YES];//將NSData類型對(duì)象data寫入文件骂删,文件名為FileName
最后:從文件中讀出數(shù)據(jù):
[NSData dataWithContentsOfFile:FileName options:0 error:NULL];//從FileName中讀取出數(shù)據(jù)
2.NSKeyedArchiver:采用歸檔的形式來保存數(shù)據(jù)掌动,該數(shù)據(jù)對(duì)象需要遵守NSCoding協(xié)議,并且該對(duì)象對(duì)應(yīng)的類必須提供encodeWithCoder:和initWithCoder:方法桃漾。前一個(gè)方法告訴系統(tǒng)怎么對(duì)對(duì)象進(jìn)行編碼坏匪,而后一個(gè)方法則是告訴系統(tǒng)怎么對(duì)對(duì)象進(jìn)行解碼
@interface Person:NSObject<NSCoding>{//遵守NSCoding協(xié)議
NSString *name;//待歸檔類型
}
@implementation Person
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:name forKey:@"name"];
}
-(void)initWithCoder:(NSCoder *)aDecoder{
name=[[aDeCoder decodeObjectforKey:@"name"] retain];**
}
歸檔操作:
對(duì)Person對(duì)象歸檔操作
//將復(fù)雜對(duì)象歸檔之后存入本地
//第一步:創(chuàng)建一個(gè)NSMutableData 用于初始化歸檔工具
NSMutableData *data = [NSMutableData data];
//第二步: 創(chuàng)建一個(gè)歸檔工具
NSKeyedArchiver *keyedArchiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//第三步:使用歸檔工具 對(duì)需要?dú)w檔的對(duì)象進(jìn)行歸檔
[keyedArchiver encodeObject:person forKey:@"person"];
//第四步: 結(jié)束歸檔
[keyedArchiver finishEncoding];
NSLog(@"data3 === %@",data);
NSString *filePath = [documentPathStr stringByAppendingPathComponent:@"person.plist"];
[data writeToFile:filePath atomically:YES];
NSLog(@"filePath == %@",filePath);
缺點(diǎn):歸檔的形式來保存數(shù)據(jù),只能一次性歸檔保存以及一次性解壓撬统。所以只能針對(duì)小量數(shù)據(jù)适滓,而且對(duì)數(shù)據(jù)操作比較笨拙,即如果想改動(dòng)數(shù)據(jù)的某一小部分恋追,還是需要解壓整個(gè)數(shù)據(jù)或者歸檔整個(gè)數(shù)據(jù)凭迹。歸檔數(shù)據(jù)儲(chǔ)存到本地實(shí)際上還是采用直接寫入本地的方式
3.NSUserDefaults:用來保存應(yīng)用程序設(shè)置和屬性罚屋、用戶保存的數(shù)據(jù)。用戶再次打開程序或開機(jī)后這些數(shù)據(jù)仍然存在嗅绸。NSUserDefaults可以存儲(chǔ)的數(shù)據(jù)類型包括:NSData脾猛、NSString、NSNumber鱼鸠、NSDate猛拴、NSArray、NSDictionary蚀狰。如果要存儲(chǔ)其他類型愉昆,則需要轉(zhuǎn)換為前面的類型,才能用NSUserDefaults存儲(chǔ)麻蹋。
具體實(shí)現(xiàn)為:
保存數(shù)據(jù):
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
NSString *name = @”default string“;
[defaults setObject:firstName forKey:@"name"];
//獲得UIImage實(shí)例
UIImage *image = [[UIImage alloc] initWithContentsOfFile:@"photo.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 100);//UIImage對(duì)象轉(zhuǎn)換成NSData
[defaults synchronize];//用synchronize方法把數(shù)據(jù)持久化到standardUserDefaults[數(shù)據(jù)庫(kù)]
讀取數(shù)據(jù):
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:@"name"];//根據(jù)鍵值取出name
NSData *imageData = [defaults dataForKey:@"image"];
UIImage *Image = [UIImage imageWithData:imageData];//NSData轉(zhuǎn)換為UIImage
4. SQLite:采用SQLite數(shù)據(jù)庫(kù)來存儲(chǔ)數(shù)據(jù)跛溉。
第一步:需要添加SQLite相關(guān)的庫(kù)以及頭文件:
在項(xiàng)目文件的Build Phases下,找到Link Binary With Libraries扮授,添加libsqlite3.0.tbd芳室;
PS:libsqlite3.0.tbd和libsqlite3.tbd的區(qū)別
使用過sqlite的同學(xué)都會(huì)發(fā)現(xiàn)在加載sqlite類庫(kù)的時(shí)候會(huì)出現(xiàn)兩個(gè)libsqlite3.0.dylib和libsqlite3.dylib,之前我一直以為它們是兩個(gè)版本的刹勃,但是后來發(fā)現(xiàn)其實(shí)libsqlite3.0.dylib本身是一個(gè)連接堪侯,它指向libsqlite3.dylib,如圖所示:
我相信這個(gè)圖就能向大家說明一切荔仁,但是這里就有疑問了抖格,直接引用libsqlite3.dylib不就行了,為什么要用libsqlite3.0.dylib咕晋,其實(shí)這個(gè)指針總是指向最新的sqlite3動(dòng)態(tài)庫(kù)雹拄,比如說sqlite3庫(kù)更新了,如果我們引用的是libsqlite3.0.dylib你就不需要做任何修改了掌呜。
第二步:開始使用SQLite:
//1.打開數(shù)據(jù)庫(kù)
//2.對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作
//3.關(guān)閉數(shù)據(jù)庫(kù)
5.使用CoreData存儲(chǔ)數(shù)據(jù)
1.Core Data 是數(shù)據(jù)持久化存儲(chǔ)的最佳方式
2.數(shù)據(jù)最終的存儲(chǔ)類型可以是:SQLite數(shù)據(jù)庫(kù)滓玖,XML,二進(jìn)制质蕉,內(nèi)存里势篡,或自定義數(shù)據(jù)類型
3.好處:能夠合理管理內(nèi)存,避免使用sql的麻煩模暗,高效
4.構(gòu)成:
(1)NSManagedObjectContext(被管理的數(shù)據(jù)上下文)
操作實(shí)際內(nèi)容(操作持久層)
作用:插入數(shù)據(jù)禁悠,查詢數(shù)據(jù),刪除數(shù)據(jù)
(2)NSManagedObjectModel(被管理的數(shù)據(jù)模型)
數(shù)據(jù)庫(kù)所有表格或數(shù)據(jù)結(jié)構(gòu)兑宇,包含各實(shí)體的定義信息
作用:添加實(shí)體的屬性碍侦,建立屬性之間的關(guān)系
操作方法:視圖編輯器,或代碼
(3)NSPersistentStoreCoordinator(持久化存儲(chǔ)助理)
相當(dāng)于數(shù)據(jù)庫(kù)的連接器
作用:設(shè)置數(shù)據(jù)存儲(chǔ)的名字,位置瓷产,存儲(chǔ)方式站玄,和存儲(chǔ)時(shí)機(jī)
(4)NSManagedObject(被管理的數(shù)據(jù)記錄)
相當(dāng)于數(shù)據(jù)庫(kù)中的表格記錄
(5)NSFetchRequest(獲取數(shù)據(jù)的請(qǐng)求)
相當(dāng)于查詢語句
(6)NSEntityDescription(實(shí)體結(jié)構(gòu))
相當(dāng)于表格結(jié)構(gòu)
(7)后綴為.xcdatamodeld的包
里面是.xcdatamodel文件,用數(shù)據(jù)模型編輯器編輯
編譯后為.momd或.mom文件