輕量級數(shù)據(jù)庫NSUserDefaults使用全解

在iOS開發(fā)過程中,進(jìn)行數(shù)據(jù)本地存儲是主要的模塊之一,在進(jìn)行數(shù)據(jù)存儲的時候有多種情況夫晌,有些時候需要大型的數(shù)據(jù)存儲,毋容置疑需要用FMDB等數(shù)據(jù)庫存儲方法昧诱;但是有些時候存儲一些輕量級的數(shù)據(jù)晓淀,僅僅是存儲一些用戶的信息(用戶ID、賬號盏档、密碼凶掰、昵稱等)簡單數(shù)據(jù),使用NSUserDefaults是首選蜈亩,它是一個單例類懦窘,通過鍵值對的方式記錄設(shè)置,用于數(shù)據(jù)的本地永久化存儲勺拣,而且NSUserDefaults使用起來非常簡單方便奶赠。那么本篇文章就來深入的探討一下NSUserDefaults的使用。

一药有、NSUserDefaults的基本概念

簡單來說毅戈,NSUserDefaults是iOS系統(tǒng)提供的一個單例類,在整個程序中只有一個實例對象愤惰,通過類方法standardUserDefaults可以獲取NSUserDefaults單例苇经。eg:NSUserDefaults? *userDefaults = [NSUserDefaults standardUserDefaults];

NSUserDefaults單例是以key-value的形式存儲了一系列的偏好設(shè)置或者一些設(shè)置的記錄,key是鍵名稱宦言,value是對應(yīng)的數(shù)據(jù)扇单。存/取數(shù)據(jù)時可以使用方法objectForKey:和setObject:forKey:來把對象存儲到相應(yīng)的plist文件中,或者讀取奠旺。既然是plist文件蜘澜,那么對象的類型則必須是plist文件可以存儲的類型施流。

使用NSUserDefaults存儲自定義對象需要注意的是,NSUserDefaults只支持以下數(shù)據(jù)類型的存儲:NSString鄙信,NSDate瞪醋,NSNumber(NSInteger、float装诡、double)银受,NSArray,NSDictionary鸦采,BOOL. 如果想要存儲其他類型的數(shù)據(jù)宾巍,需要轉(zhuǎn)換為前面的類型,才能用NSUserDefaults存儲渔伯。注意:對相同的Key賦值約等于一次覆蓋顶霞,要保證每一個Key的唯一性。

可是還需要注意一點:如果把一個自定義的類存到一個NSArray里咱旱,然后再存到NSUserDefaults里也是不能操作成功的确丢。NSUserDefaults存儲的對象全是不可變的(這一點非常重要)绷耍,eg:如果我想存儲一個NSMutableArray對象吐限,我必須先創(chuàng)建一個不可變數(shù)組NSArray,再將它存入NSUserDefaults中去褂始;eg:如果設(shè)置一個可變的字符串值作為"StringDefault”你日后檢索字符串使用诸典,stringForKey:會是一成不變的。

如果需要存儲plist文件不支持的類型崎苗,比如圖片狐粱,可以先將其歸檔為NSData類型,再存入plist文件胆数,可是需要注意的是:即使對象是NSArray或NSDictionary肌蜻,他們存儲的類型也應(yīng)該是以上范圍所包括的。

二必尼、NSUserDefaults的基本用法

1蒋搜、NSUserDefaults的保存數(shù)據(jù):

NSUserDefaults *userDefaults =[NSUserDefaults standardUserDefaults];

[userDefaults setObject:firstName forKey:@”kUserDefaultNameKey“];

NSInteger age = [defaults integerForKey:@“kUserDefaultAgeKey”]; //這里的NSInteger沒有星號,是因為NSInteger是根據(jù)系統(tǒng)是64位還是32位來判斷自身是long還是int的類型判莉,并且它不是一個標(biāo)準(zhǔn)的Objective-C對象

?//UIImage做本地存儲的步驟豆挽,圖片是通過歸檔為NSData的方式進(jìn)行存儲的

UIImage *image=[[UIImage alloc]initWithContentsOfFile:@"photo.jpg"];

NSData *imageData = UIImageJPEGRepresentation(image, 100); //把UIImage對象轉(zhuǎn)換成NSData

[userDefaults synchronize]; //用synchronize方法把數(shù)據(jù)持久化到standardUserDefaults數(shù)據(jù)庫

2、NSUserDefaults的讀取數(shù)據(jù):

NSUserDefaults *userDefaults =[NSUserDefaults standardUserDefaults];

NSString *name = [userDefaults objectForKey:@"name"]; //根據(jù)鍵值取出name

NSData *imageData = [userDefaults dataForKey:@"image"];

UIImage *Image = [UIImage imageWithData:imageData]; //將NSData轉(zhuǎn)換為UIImage

3券盅、NSUserDefaults的清理數(shù)據(jù):

//方法一:

[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];

[[NSUserDefaults standardUserDefaults]synchronize];

//方法二:

// 先將本地存儲轉(zhuǎn)化為字典帮哈,然后用for in遍歷刪除即可

?NSUserDefaults?*userDefaults = [NSUserDefaults?standardUserDefaults];

?NSDictionary?*dictionary = [userDefaults?dictionaryRepresentation];

?for(NSString?*key?in?[dictionary?allKeys]){

? ? ? [userDefaults?removeObjectForKey:key];

? ? ? [userDefaults?synchronize];

? }

4、不同類型數(shù)據(jù)存取不同

NSUserDefaults提供了若干簡便方法可以存儲某些常用類型的值锰镀,eg:

- setBool:forKey:

- setFloat:forKey:

- setInteger:forKey:

- setDouble:forKey:

- setURL:forKey:

三娘侍、NSUserDefaults的相關(guān)類方法

// 同步對共享對象的任何的更改默認(rèn)用戶和從內(nèi)存中釋放它

resetStandardUserDefaults

// 返回共享默認(rèn)對象

+ (NSUserDefaults *)standardUserDefaultsaddSuiteNamed:

// 插入到接收器的搜索列表中指定的域名

- (void)addSuiteNamed:( NSString *) suiteName

// 返回布爾值與指定鍵相關(guān)聯(lián)

- (BOOL)boolForKey:( NSString *) defaultName

// 返回與指定鍵相關(guān)聯(lián)的數(shù)組

- ( NSArray *)arrayForKey:( NSString *) defaultName

// 返回數(shù)據(jù)對象與指定鍵相關(guān)聯(lián)

- ( NSData *)dataForKey:( NSString *) defaultName

// 返回Dictionary對象與指定鍵相關(guān)聯(lián)

- ( NSDictionary *)dictionaryForKey:( NSString *) defaultName

// 返回一個字典咖刃,它包含在搜索列表中的域的所有鍵值對聯(lián)合( NSData , NSString 憾筏, NSNumber 僵缺, NSDate ,NSArray踩叭,或者NSDictionary )

- ( NSDictionary *)dictionaryRepresentation

// 消除了在標(biāo)準(zhǔn)應(yīng)用程序域指定的默認(rèn)鍵值

- (void)removeObjectForKey:( NSString *) defaultName

// 刪除指定的從用戶的默認(rèn)持久域的內(nèi)容

- (void)removePersistentDomainForName:( NSString *) domainName

// 設(shè)置指定的默認(rèn)鍵到指定的布爾值

- (void)setBool:(BOOL) value forKey:( NSString *) defaultName

// 設(shè)置為指定的字典持久域

- (void)setPersistentDomain:( NSDictionary *) domain forName:( NSString *) domainName

// 設(shè)置指定的默認(rèn)鍵到指定的URL值

- (void)setURL:( NSURL *) url forKey:( NSString *) defaultName

// 設(shè)置為指定的字典揮發(fā)性域

- (void)setVolatileDomain:( NSDictionary *) domain forName:( NSString *) domainName

// 返回與指定鍵關(guān)聯(lián)的字符串?dāng)?shù)組

- ( NSArray *)stringArrayForKey:( NSString *) defaultName

// 返回與指定鍵關(guān)聯(lián)的字符串

- ( NSString *)stringForKey:( NSString *) defaultName

//返回NSURL實例與指定鍵相關(guān)聯(lián)

- ( NSURL *)URLForKey:( NSString *) defaultName?

// 返回double值與指定鍵相關(guān)聯(lián)

- (double)doubleForKey:( NSString *) defaultName

// 返回浮點值與指定鍵相關(guān)聯(lián)

- (float)floatForKey:( NSString *) defaultName

// 返回NSUserDefaults對象初始化的用戶帳戶的默認(rèn)為指定的

- (id)initWithUser:( NSString *) username

// 返回整數(shù)值與指定鍵關(guān)聯(lián)

- ( NSInteger NSInteger )integerForKey:( NSString *) defaultName

// 判斷這個key是否存在

- (BOOL)objectIsForcedForKey:( NSString *) key

// 返回與指定默認(rèn)的第一個發(fā)生關(guān)聯(lián)的對象

- (id)objectForKey:( NSString *) defaultName

四裤园、NSUserDefaults的域

BOOL showTutorialOnLaunch = [[NSUserDefaults standardUserDefaults] boolForKey:@"ShowTutorial"];

這種情況下,當(dāng)key值@“ShowTutorial”已經(jīng)設(shè)置后就會運行正確韧拒,但如果默認(rèn)數(shù)據(jù)庫沒有這個key的默認(rèn)值時楼眷,就返回NO,這或許就不一定是需要的值了斤富,因為系統(tǒng)無法區(qū)分NO和no value膏潮。

以上解決方式:使用registerDefaults:方法

首先創(chuàng)建一個包含用戶偏好設(shè)置信息的DefaultPreferences.plist文件,添加到target中满力。在運行時焕参,App就可加載這個文件并且把內(nèi)容傳到registerDefaults :

NSURL *defaultPrefsFile = [[NSBundle mainBundle]

URLForResource:@"DefaultPreferences" withExtension:@"plist"];

NSDictionary *defaultPrefs = [NSDictionary dictionaryWithContentsOfURL:defaultPrefsFile];

[[NSUserDefaults standardUserDefaults] registerDefaults:defaultPrefs];

注意:需要在每次啟動app并且沒有在defaules中讀取數(shù)據(jù)的時候調(diào)用以上方法,因為registerDefaults:不能把這些默認(rèn)數(shù)據(jù)存儲到硬盤上油额,所以方法application:didFinishLaunchingWithOptions是最合適的位置叠纷。

這樣做法的原因:默認(rèn)情況下,應(yīng)用域是空的潦嘶,沒見鍵也沒有值涩嚣。當(dāng)應(yīng)用第一次設(shè)置某項用戶偏好設(shè)置的值時,相應(yīng)的值會通過指定的鍵加入應(yīng)用域掂僵。當(dāng)通過NSUserDefaults獲取某項用戶偏好設(shè)置的值時航厚,NSUserDefaults會先在應(yīng)用域中查找,如果找到了值锰蓬,NSUserDefaults就會返回這個值幔睬。如果沒找到,NSUserDefaults就會在注冊域中查找并返回默認(rèn)值芹扭。

域:

user defaults數(shù)據(jù)庫之中其實是由多個層級的域組成的麻顶,當(dāng)你讀取一個鍵值的數(shù)據(jù)時,NSUserDefaults從上到下透過域的層級尋找正確的值冯勉,不同的域有不同的功能澈蚌,有些域是可持久的,有些域則不行灼狰。

應(yīng)用域(application domain)是最重要的域宛瞄,它存儲著App通過NSUserDefaults set...forKey添加的設(shè)置;

注冊域(registration domain)僅有較低的優(yōu)先權(quán),只有在應(yīng)用域沒有找到值時才從注冊域去尋找份汗;

全局域(global domain)是存儲著系統(tǒng)的設(shè)置盈电;

語言域(language-specific domains)包括地區(qū)、日期等杯活;

參數(shù)域( argument domain)有最高優(yōu)先權(quán)匆帚。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市旁钧,隨后出現(xiàn)的幾起案子吸重,更是在濱河造成了極大的恐慌,老刑警劉巖歪今,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嚎幸,死亡現(xiàn)場離奇詭異,居然都是意外死亡寄猩,警方通過查閱死者的電腦和手機嫉晶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來田篇,“玉大人替废,你說我怎么就攤上這事〔醇恚” “怎么了椎镣?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長彬呻。 經(jīng)常有香客問我衣陶,道長,這世上最難降的妖魔是什么闸氮? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮教沾,結(jié)果婚禮上蒲跨,老公的妹妹穿的比我還像新娘。我一直安慰自己授翻,他們只是感情好或悲,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著堪唐,像睡著了一般巡语。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上淮菠,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天男公,我揣著相機與錄音,去河邊找鬼合陵。 笑死枢赔,一個胖子當(dāng)著我的面吹牛澄阳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播踏拜,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼碎赢,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了速梗?” 一聲冷哼從身側(cè)響起肮塞,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎姻锁,沒想到半個月后峦嗤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡屋摔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年烁设,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钓试。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡装黑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弓熏,到底是詐尸還是另有隱情恋谭,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布挽鞠,位于F島的核電站疚颊,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏信认。R本人自食惡果不足惜材义,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嫁赏。 院中可真熱鬧其掂,春花似錦、人聲如沸潦蝇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽攘乒。三九已至贤牛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間则酝,已是汗流浹背殉簸。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喂链。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓返十,卻偏偏與公主長得像,于是被迫代替她去往敵國和親椭微。 傳聞我的和親對象是個殘疾皇子洞坑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

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