iOS 運用NSUserDefaults保存數(shù)據(jù)實現(xiàn)數(shù)據(jù)緩存

應(yīng)同學(xué)之約陨仅,抽個時間立轧,寫篇關(guān)于 NSUserDefaults 實現(xiàn)保存數(shù)據(jù)的文章既鞠。
確實在項目中稼跳,雖然我們數(shù)據(jù)都是通過 API ,從后臺獲取物臂,但是很多時候瘟滨,我們需要做數(shù)據(jù)的本地緩保锯蛀,以便實現(xiàn)我們在沒有網(wǎng)絡(luò)的時候可以讀取本地數(shù)據(jù),而不致于說獲取不到數(shù)據(jù)馅精,整個頁面都空白的尷尬严嗜。還有如果是已經(jīng)有本地數(shù)據(jù)緩保,那么就不用每次都從通過網(wǎng)絡(luò)從后臺獲取洲敢,可以提高用戶體驗漫玄,也不至于浪費太多用戶的流量。我們就先討論這兩種簡單的情況压彭,其他特殊情況先排除開來睦优。
那么一般我們接觸到的本地存儲數(shù)據(jù)就幾種:
1,歸檔寫入沙盒

[str writeToFile:strFilePath atomically:YES encoding:NSUTF8StringEncoding error:&error];

2哮塞,數(shù)據(jù)庫
可以借助 FMDB 等第三方庫去實現(xiàn)

3刨秆,NSUserDefaults

當(dāng)然大神如果有不同見解凳谦,歡迎提出忆畅。
這三種方法也是各有利弊,至于有什么不同尸执,跟優(yōu)缺點家凯,大家就自行百度、google吧如失,這里就不講太多绊诲。
今天我們就主要講一下第3種,最簡單粗暴的方法褪贵。

NSUserDefaults是一個單例掂之,在整個程序中只有一個實例對象,而且不同于我們自己定義的單例脆丁,因為他不會隨著這個程序的關(guān)閉而清除掉保存的數(shù)據(jù)世舰,下次你開啟程序,你之前保存的數(shù)據(jù)還是存在的槽卫,所以他可以用于本地數(shù)據(jù)的持久化跟压,而且簡單實用,我們也可以用來做為頁面間的傳值歼培。
NSUserDefaults支持的數(shù)據(jù)類型有:NSNumber(NSInteger震蒋、float、double)躲庄,NSString查剖,NSDate,NSArray噪窘,NSDictionary笋庄,BOOL.
其實他的用法非常簡單,跟我們平時使用字典基本一樣。一個key无切,一個Value荡短。
就比如說,我們在做登陸功能的時候哆键,基本上都要記住用戶的用戶名掘托,下次用戶再打開APP的時候,登陸的時候就不用再輸入用戶名了籍嘹。保存代碼如下:

    //將NSString 對象存儲到 NSUserDefaults 中
    NSString *userName = @"Jimmy.Lin";
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:userName forKey:@"saveUserName"];

那么下次打開登陸頁面的時候闪盔,就可以直接從NSUserDefaults中取出我們所保存的用戶名,直接使用了辱士。取出保存的數(shù)據(jù)代碼如下:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    // 這里用到的 key 就是上次我們保存的時候所使用的 key
    NSString *userName = [ defaults objectForKey:@"saveUserName"];

這里需要注意一點泪掀,就是如果你不想數(shù)據(jù)被覆蓋掉,那就需要使用不同的key颂碘,換句話講异赫,就是你現(xiàn)在里面已經(jīng)用"saveUserName"這個 key 保存了這一次的用戶名,如果你再使用同樣的這一個 key 保存數(shù)據(jù)的話头岔,那第二次的 value 會覆蓋掉第一次的 value塔拳,就是你再次取值的時候,取出來的就是第二次所保存的 value 了峡竣。

恩靠抑,講到這里,也許你會在使用過程中适掰,出現(xiàn)你寫了保存的代碼颂碧,但是你再次取值的時候卻取不出你之前保存的值,心里估計在罵娘 类浪,尼瑪载城,蘋果這么垃圾,自己的方法都出錯戚宦,還讓我們用个曙。
不用慌,NSUserDefaults偶爾不工作受楼,無法保存改動的數(shù)據(jù)的原因是垦搬,NSUserDefaults的機(jī)制是,過一段時間艳汽,會自動調(diào)用自己的函數(shù)synchronize去同步數(shù)據(jù)的猴贰。
而如果你是遇到和我此處類似的,改動數(shù)據(jù)后河狐,就退出程序了米绕,即在NSUserDefaults還沒來得及synchronize之前就退出程序瑟捣,就需要手動調(diào)用synchronize去保存數(shù)據(jù)了。
也就是說我們可以手動調(diào)用NSUserDefaults去執(zhí)行同步synchronize的動作栅干,以及時保存(修改了的)數(shù)據(jù)迈套。
那么為了確保萬無一失,我們把上面的保存代碼完善一下:

//將NSString 對象存儲到 NSUserDefaults 中
    NSString *userName = @"Jimmy.Lin";
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:userName forKey:@"saveUserName"];
    // 手動調(diào)用NSUserDefaults去執(zhí)行同步synchronize的動作碱鳞,以及時保存(修改了的)數(shù)據(jù)
    [defaults synchronize];

OK桑李,再也不會出現(xiàn)坑爹的保存了數(shù)據(jù)取不出來值的情況了。

上面講的是簡單的保存簡單的字符串窿给,但是一般我們用后臺獲取到的數(shù)據(jù)都是 json 贵白,那么我們轉(zhuǎn)化完之后,就是字典或者數(shù)組了崩泡。那同樣的禁荒,這些數(shù)據(jù)也是一樣的保存。

    // 保存數(shù)組
    NSArray *arr = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9"];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:arr forKey:@"saveArray"];
    [defaults synchronize];
    // 讀取我們保存的數(shù)組
    NSArray *getArr = [defaults objectForKey:@"saveArray"];
    // 打印出來看看是否正確
    for (NSString *number in getArr) {
        NSLog(@"number = %@",number);
    }

打印結(jié)果如下角撞,正確呛伴,perfect


打印結(jié)果

保存字典的用法一樣,這里就不重復(fù)了靴寂。

這里同樣有一點是需要特別注意的磷蜀,就是NSUserDefaults保存的數(shù)據(jù)全是不可變的!0倬妗!這一點是非常重要的污它,弄錯的話會有 bug 剖踊。到時候別說我是照著這方法保存的,拿出來用衫贬,卻崩了德澈。真的不是這個方法有問題!

當(dāng)然如果你只是保存的話是沒什么問題的固惯,也不會出現(xiàn)程序崩的情況:


保存可變數(shù)組正常

按上面的代碼來的話梆造,運行完發(fā)現(xiàn)也能拿到我們要的結(jié)果,一切正常葬毫,那是不是覺得我們拿到的就是我們保存的可變數(shù)組镇辉?
那我們來驗證一下,如果真的是可變數(shù)據(jù)贴捡,那就可以添加刪除里面的元素:


添加元素驗證

再次運行忽肛,發(fā)現(xiàn)崩了±谜看一下程序崩潰原因:


崩潰原因

看到這屹逛,很好理解吧础废。我們拿出來的是一個不可變數(shù)組!所以你添加元素的話肯定就崩啦罕模!

那如果我就是非要往拿出來的數(shù)組里面添加元素怎么辦呢评腺?很簡單,先轉(zhuǎn)成可變的淑掌,再添加歇僧,然后再用同樣的 key 保存進(jìn)去覆蓋掉之前的數(shù)據(jù)就搞定了:


往取出來的數(shù)組添加元素

OK,運行一下锋拖,打印出來的結(jié)果诈悍,已經(jīng)添加進(jìn)去了:


添加成功

恩。好像用法就是這么簡單兽埃!看到這里是不是覺得這貨不就是一個字典嗎侥钳?所以你會用字典,這貨你也肯定會用 柄错,so easy 舷夺!

但是問題又來了,數(shù)據(jù)拿到的時候是 json 售貌,但是我們基本上都是轉(zhuǎn)換成 model 给猾,然后放進(jìn)數(shù)組里面,這樣方便后期處理跟使用颂跨「疑欤看一下上面講的 NSUserDefaults 能保存的數(shù)據(jù)類型,model 明顯是不行的恒削。但是別忘了 iOS 強(qiáng)大的數(shù)據(jù)轉(zhuǎn)化池颈,看一下,NSUserDefaults可以保存 NSData 的數(shù)據(jù)類型钓丰,那么就好辦了躯砰,只不過是需要多繞一個圈而已。那么怎么來實現(xiàn)這些自定義 model 的數(shù)據(jù)保存呢携丁?
還是讓我們一步一步來吧琢歇,首先,那先定義一個 model 類梦鉴,里面就簡單的加三個屬性吧李茫,為了方便,我們再添加一個初始化方法:


定義 Model 類

那我們要實現(xiàn)將 model 類轉(zhuǎn)換成 NSData 類型的尚揣,就必須歸檔涌矢,這里要實現(xiàn) 在.h 文件中遵循 NSCoding 協(xié)議,再 在 .m 中實現(xiàn) encodeWithCoder 方法 和
initWithCoder 方法就可以了 :


遵循 NSCoding 協(xié)議

在 .m 文件里實現(xiàn)我們上面自定義的初始化方法快骗,跟 NSCoding 協(xié)議方法:


.m 文件需要實現(xiàn)的方法

這樣做就可以將我們自定義的 model 類型轉(zhuǎn)變?yōu)?NSData 類型了娜庇。
直接上代碼吧:


保存自定義的 model 數(shù)組

看一下打印結(jié)果:


驗證結(jié)果

好了塔次,到這基本上也沒什么好講的了,都是很簡單的用法名秀,至少比第1種励负,第2種方法使用起來簡單太多了!
不過用 NSUserDefaults 保存數(shù)據(jù)的話匕得,要考慮的問題就是安全性继榆!至于你要用加密還是什么別的方法的話,我在這就不多加討論了汁掠,因為每個公司每個人處理的方法都不一樣略吨。

希望大家以后不會再為這簡單的數(shù)據(jù)保存問題頭疼了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末考阱,一起剝皮案震驚了整個濱河市翠忠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乞榨,老刑警劉巖秽之,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吃既,居然都是意外死亡考榨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門鹦倚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來河质,“玉大人,你說我怎么就攤上這事申鱼》哂眨” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵捐友,是天一觀的道長。 經(jīng)常有香客問我溃槐,道長匣砖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任昏滴,我火速辦了婚禮猴鲫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谣殊。我一直安慰自己拂共,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布姻几。 她就那樣靜靜地躺著宜狐,像睡著了一般势告。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抚恒,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天咱台,我揣著相機(jī)與錄音,去河邊找鬼俭驮。 笑死回溺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的混萝。 我是一名探鬼主播遗遵,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逸嘀!你這毒婦竟也來了车要?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤厘熟,失蹤者是張志新(化名)和其女友劉穎屯蹦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绳姨,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡登澜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了飘庄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脑蠕。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖跪削,靈堂內(nèi)的尸體忽然破棺而出谴仙,到底是詐尸還是另有隱情,我是刑警寧澤碾盐,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布晃跺,位于F島的核電站,受9級特大地震影響毫玖,放射性物質(zhì)發(fā)生泄漏掀虎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一付枫、第九天 我趴在偏房一處隱蔽的房頂上張望烹玉。 院中可真熱鬧,春花似錦阐滩、人聲如沸二打。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽继效。三九已至症杏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間莲趣,已是汗流浹背鸳慈。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留喧伞,地道東北人走芋。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像潘鲫,于是被迫代替她去往敵國和親翁逞。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

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