本地持久化存儲(chǔ)

一、沙盒機(jī)制

沙盒是什么

每個(gè)iOS應(yīng)用都有屬于自己的應(yīng)用沙盒(沙盒就是文件系統(tǒng)目錄)夫偶,與其他文件系統(tǒng)隔離,每個(gè)應(yīng)用都只能訪問自己的沙盒觉增。

沙盒的路徑結(jié)構(gòu)

  • Document:適合存儲(chǔ)重要的數(shù)據(jù)兵拢, iTunes同步應(yīng)用時(shí)會(huì)同步該文件下的內(nèi)容,(比如游戲中的存檔)
 NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
  • Library/Caches:適合存儲(chǔ)體積大逾礁,不需要備份的非重要數(shù)據(jù)说铃,iTunes不會(huì)同步該文件
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
  • Library/Preferences: 通常保存應(yīng)用的設(shè)置信息, iTunes同步該應(yīng)用時(shí)會(huì)同步此文件夾中的內(nèi)容
  • tmp:保存應(yīng)用的臨時(shí)文件,用完就刪除嘹履,系統(tǒng)可能在應(yīng)用沒在運(yùn)行時(shí)刪除該目錄下的文件腻扇,iTunes不會(huì)同步該文件
NSString *path = NSTemporaryDirectory();

獲取沙盒路徑

通過NSSearchPathForDirectoriesInDomains 方法來獲取沙盒路徑

二、數(shù)據(jù)存儲(chǔ)常用方式

偏好設(shè)置(NSUserDefaults)

  • 偏好設(shè)置是專門保存應(yīng)用的配置信息的砾嫉,如用戶名幼苛、密碼等,一般不要在偏好設(shè)置中保存其他數(shù)據(jù)焕刮。
  • NSUserDefaults保存的數(shù)據(jù)都是不可變的舶沿,取出來的數(shù)據(jù)也是不可變類型墙杯,通過鍵值對方式進(jìn)行存取。
  • 如果沒有調(diào)用synchronize方法括荡,系統(tǒng)會(huì)根據(jù)I/O情況不定時(shí)刻地保存到文件中高镐。所以如果需要立即寫入文件的就必須調(diào)用synchronize方法。
  • 偏好設(shè)置會(huì)將所有數(shù)據(jù)保存到同一個(gè)文件中畸冲。即preference目錄下的一個(gè)以此應(yīng)用包名來命名的plist文件嫉髓。

實(shí)例如下:

//獲得NSUserDefaults文件
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//保存內(nèi)容
[userDefaults setValue:@"sunsan" forKey:username];
[userDefaults setValue:@"abcd1234" forKey:userpassword];
//讀取內(nèi)容
NSString * name = [userDefaults valueForKey:username];
NSString * password = [userDefaults valueForKey:userpassword];

plist存儲(chǔ)

plist文件是將某些特定的類,通過XML文件的方式保存在目錄中邑闲。
可以被序列化的類型有以下幾種:

NSArray;
NSMutableArray;
NSDictionary;
NSMutableDictionary;
NSData;
NSMutableData;
NSString;
NSMutableString;
NSNumber;
NSDate;

實(shí)例如下:

//設(shè)置文件名
NSString *fileName = [path stringByAppendingPathComponent:@"students.plist"];
//寫入文件
[array writeToFile:fileName atomically:YES];
//讀取
NSArray *result = [NSArray arrayWithContentsOfFile:fileName];

歸檔解歸檔

通過使用NSKeyArchiverarchiveRootObject: toFile:方法直接歸檔一個(gè)對象算行,使用NSKeyedUnarchiverunarchiveObjectWithFile:解檔對象。
在歸檔自定義對象的時(shí)候监憎,必須遵守NSCoding協(xié)議纱意,并實(shí)現(xiàn)協(xié)議方法:

  • 每次歸檔對象時(shí),都會(huì)調(diào)用encodeWithCoder:鲸阔,一般在這個(gè)方法里面指定如何歸檔對象中的每個(gè)實(shí)例變量偷霉;
  • 每次從文件中恢復(fù)對象時(shí),都會(huì)調(diào)用initWithCoder:褐筛,一般在這個(gè)方法里面指定如何解碼文件中的數(shù)據(jù)為對象的實(shí)例變量类少。

實(shí)例如下:

//設(shè)置文件名
NSString *fileName = [path stringByAppendingPathComponent:@"person.archiver"];
//進(jìn)行歸檔
[NSKeyedArchiver archiveRootObject:per toFile:fileName];
//進(jìn)行解歸檔
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:fileName];

以上的存儲(chǔ)方法,都是覆蓋存儲(chǔ)渔扎。如果想要增加一條數(shù)據(jù)就必須把整個(gè)文件讀出來硫狞,然后修改數(shù)據(jù)后再把整個(gè)內(nèi)容覆蓋寫入文件,并不適合大量數(shù)據(jù)的存取晃痴。


SQLite

SQLite簡介

SQLite是一個(gè)輕量級關(guān)系數(shù)據(jù)庫残吩,最初的設(shè)計(jì)目標(biāo)是用于嵌入式系統(tǒng),它占用資源非常少倘核。在iOS中泣侮,只要導(dǎo)入libsqlite3.0.tbd依賴以及引入sqlite3.h頭文件即可。
SQLite是無類型的數(shù)據(jù)庫紧唱,可以保存任何類型的數(shù)據(jù)活尊,對于SQLite來說對字段不指定類型是完全有效的

SQLite近似類似規(guī)則

  • 如果類型字符串中包含“int”,那么該字段的親緣關(guān)系是INTEGER
  • 如果類型字符串中包含“char”漏益,“clob”或“text”蛹锰,那么該字段的親緣類型是TEXT
  • 如果類型字符串中包含“blob”,那么該字段的親緣類型是NONE
  • 如果類型字符串中包含“real”绰疤,“floa”或“doub”铜犬,那么該字段的親緣類型是REAL
  • 其余情況下,字段的親緣類型為NUMERIC

SQLite字段的約束條件

  • not null —— 非空
  • unique —— 唯一
  • primary key —— 主鍵
  • foreign key —— 外鍵
  • check —— 條件檢查,確保一列中所有的值滿足一定條件
  • default —— 默認(rèn)
  • autoincrement —— 自增型變量翎苫,該字段數(shù)據(jù)如果為整形可以自動(dòng)加1

SQLite語句

SQL語言共分為四大類:數(shù)據(jù)查詢語言DQL权埠,數(shù)據(jù)操縱語言DML,數(shù)據(jù)定義語言DDL煎谍,數(shù)據(jù)控制語言DCL攘蔽。

  • DML主要包含數(shù)據(jù)的增刪改:
    數(shù)據(jù)插入(insert):insert into 表名(字段1,字段2呐粘,……)values(字段1值满俗,字段2值,……)
    數(shù)據(jù)更新(update):update 表名 set 字段1=修改值1作岖,字段2=修改值2唆垃,……where 條件
    數(shù)據(jù)刪除(delete):delete from 表名 where 條件
  • DQL主要用于查詢獲得表中的數(shù)據(jù),其中差用的關(guān)鍵字包含where痘儡,order by辕万,group by和having
    數(shù)據(jù)查詢(select):select 查找字段 from 表名 where 條件
  • DDL部分包含創(chuàng)建或者刪除表格,定義索引沉删,規(guī)定表之間的鏈接渐尿,以及施加表間的約束
    建表命令:create table if not exists 表名(字段1 約束1 約束2……,字段2 約束1 約束2)
    刪表命令:drop table if exists 表名

FMDB

FMDB是一款輕量級的框架矾瑰,以O(shè)C的方式對SQLite的C語言API進(jìn)行封裝砖茸,對多線程并發(fā)進(jìn)行處理,所以線程安全殴穴。

FMDB常用類

FMDatabase:一個(gè)FMDatabase對象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫凉夯,用來執(zhí)行SQL語句
FMResultSet:使用FMDatabase執(zhí)行查詢后的結(jié)果集
FMDatabaseQueue:用于在多線程中執(zhí)行多個(gè)查詢或更新,它是線程安全的

FMDB操作

  • 使用FMDataBase類建立數(shù)據(jù)庫
//獲取Documents路徑
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject ;
//生成數(shù)據(jù)庫路徑
NSString *filePath = [path stringByAppendingPathComponent:@"person.sqlite"];
//獲取數(shù)據(jù)庫
database = [FMDatabase databaseWithPath:filePath];
if ([database open]) {
    NSLog(@"數(shù)據(jù)庫打開成功");
}else{
    NSLog(@"打開數(shù)據(jù)庫失敗");
}
  • 表的創(chuàng)建
BOOL result = [database executeUpdate:@"create table if not exists person (name text primary key not null, city text, age integer)"];
if (result) {
    NSLog(@"創(chuàng)建表成功");
} else {
    NSLog(@"創(chuàng)建表失敗");
}
  • 添加數(shù)據(jù)
BOOL result = [database executeUpdate:@"insert into person (name,city,age) values (?,?,?)",per.name,per.city,@(per.age)];
if (result) {
    NSLog(@"添加數(shù)據(jù)成功");
} else {
    NSLog(@"添加數(shù)據(jù)失敗");
}
  • 刪除數(shù)據(jù)
BOOL result = [database executeUpdate:@"delete from person where name = ?",per.name];
if (result) {
    NSLog(@"刪除數(shù)據(jù)成功");
} else {
    NSLog(@"刪除數(shù)據(jù)失敗");
}
  • 修改數(shù)據(jù)
BOOL result = [database executeUpdate:@"update person set city = ?,age = ? where name = ?",per.city,@(per.age),per.name];
if (result) {
    NSLog(@"修改數(shù)據(jù)成功");
} else {
    NSLog(@"修改數(shù)據(jù)失敗");
}
  • 查詢所有數(shù)據(jù)
FMResultSet *result = [database executeQuery:@"select * from person"];
while ([result next]) {
    Person *per = [[Person alloc] init];
    per.name = [result stringForColumn:@"name"];
    per.city = [result stringForColumn:@"city"];
    per.age =  [result intForColumn:@"age"];
     [array addObject:per];
}
  • 關(guān)閉數(shù)據(jù)庫
if ([database close]) {
    NSLog(@"關(guān)閉數(shù)據(jù)庫成功");
} else {
    NSLog(@"關(guān)閉數(shù)據(jù)庫失敗");
}

參考:完整項(xiàng)目資料下載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末采幌,一起剝皮案震驚了整個(gè)濱河市劲够,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌休傍,老刑警劉巖再沧,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尊残,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)淤堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門寝衫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拐邪,你說我怎么就攤上這事慰毅。” “怎么了扎阶?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵汹胃,是天一觀的道長婶芭。 經(jīng)常有香客問我,道長着饥,這世上最難降的妖魔是什么犀农? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮宰掉,結(jié)果婚禮上呵哨,老公的妹妹穿的比我還像新娘。我一直安慰自己轨奄,他們只是感情好孟害,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挪拟,像睡著了一般挨务。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上玉组,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天谎柄,我揣著相機(jī)與錄音,去河邊找鬼球切。 笑死谷誓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吨凑。 我是一名探鬼主播捍歪,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鸵钝!你這毒婦竟也來了糙臼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤恩商,失蹤者是張志新(化名)和其女友劉穎变逃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怠堪,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揽乱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了粟矿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凰棉。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖陌粹,靈堂內(nèi)的尸體忽然破棺而出撒犀,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布或舞,位于F島的核電站荆姆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏映凳。R本人自食惡果不足惜胆筒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望魏宽。 院中可真熱鬧腐泻,春花似錦、人聲如沸队询。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚌斩。三九已至铆惑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間送膳,已是汗流浹背员魏。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留叠聋,地道東北人撕阎。 一個(gè)月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像碌补,于是被迫代替她去往敵國和親虏束。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容