NSUserDefaults官方
它底層是一個xml格式的plist文件保存在應(yīng)用程序的沙箱中。
文檔中給了開發(fā)者提供了兩個例子:
- 可以存儲一些應(yīng)用中常用的測量單位
- 存儲用戶喜歡的多媒體播放速度
其實很好理解赤屋,如果應(yīng)用中的多媒體被作為單獨模塊拆分立镶,我們很容易將用戶偏好這部分邏輯方便的放置在模塊內(nèi)部,而實際上类早,它也確實應(yīng)該被放在那里媚媒。一般來說,小規(guī)模數(shù)據(jù)涩僻,弱業(yè)務(wù)相關(guān)數(shù)據(jù)缭召,都可以放到NSUserDefault里面,內(nèi)容比較多的數(shù)據(jù)逆日,強業(yè)務(wù)相關(guān)的數(shù)據(jù)就不太適合NSUserDefault了嵌巷。
在應(yīng)用程序運行期間數(shù)據(jù)庫中的數(shù)據(jù)可以多線程讀取這個沒有問題,但是設(shè)置值的時候室抽,NSUserDefaults會在使用線程中同步的修改這個值搪哪,但是其實真正持久化到數(shù)據(jù)庫的時候是異步的。同時NSUserDefaults也提供了方法用于強制將當(dāng)前值寫入持久存儲狠半。
同時需要注意的是不要在應(yīng)用程序中自己打開那些存儲文件噩死。
Don’t try to access the preferences subsystem directly. Modifying preference property list files may result in loss of changes, delay of reflecting changes, and app crashes. To configure preferences, use the defaults command-line utility in macOS instead.
存儲默認(rèn)對象
對于一些基礎(chǔ)的默認(rèn)數(shù)據(jù)類型颤难,NSUserDefaults提供了一些便捷方法來設(shè)置他們。包括:
- float
- double
- integer
- boolean
- url
NSUserDefaults支持的可存儲的對象類型有:
- NSData
- NSString
- NSNumber
- NSDate
- NSArray
- NSDictionary
其中集合中包含的對象也必須是他們中的一員已维,不行的話就只能歸檔了行嗤。
默認(rèn)值和域
NSUserDefaults 還有一個 Domain 的概念,當(dāng)我們調(diào)用 NSUserDefaults.standardUserDefaults() 方法時垛耳,就會初始化 NSUserDefaults栅屏, 并且它默認(rèn)會包含 5 個 Domain,分別是:
- NSArgumentDomain
- Application
- NSGlobalDomain
- Languages
- NSRegistrationDomain
搜索順序如下:
NSArgumentDomain -> Application -> NSGlobalDomain -> Languages -> NSRegistrationDomain
關(guān)于這部分內(nèi)容可以參考該文:
NSUserDefaults - 熟悉與陌生
持久化文件引用
其實主要是通過在文件系統(tǒng)生成文件bookmark的做法來防止存放文件URL之后堂鲜,文件路徑被修改栈雳。
關(guān)于iOS中的URL可以參考這篇文章:
iOS-Foundation NSURL
響應(yīng)偏好改變
我們可以使用kvo來監(jiān)聽某個默認(rèn)值的變化。其中key為你存儲在用戶偏好中的值缔莲。
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self
forKeyPath:@"values.key"
options:NSKeyValueObservingOptionNew
context:NULL];
簡單點可以寫為
[[NSUserDefaults standardUserDefaults] addObserver:self
forKeyPath:@"key"
options:NSKeyValueObservingOptionNew
context:NULL];
關(guān)于沙盒的考慮
一個基于沙盒管理的App一般情況下是不能修改其他沙盒下的App的哥纫,有兩種情況例外:
- macOS 或 iOS App的extensions
- macOS中App包含在一個group中
關(guān)于這個部分有一個實際應(yīng)用。之前開發(fā)的應(yīng)用中有一個功能是收款語音播報痴奏。我采用的方案是使用app extension功能進(jìn)行開發(fā)蛀骇。其中涉及到一個需求,在主應(yīng)用中有一個控制是否播放語音的開關(guān)读拆,在extension中實現(xiàn)了合成語音并播放的功能擅憔。
-
開啟AppGroup
image.png - 初始化針對該group的用戶偏好文件
NSUserDefaults *shareUserDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.xxxx"];
if (![shareUserDefault boolForKey:@"FirstVoiceManagerProfile"]) {
[shareUserDefault setBool:YES forKey:OPEN_KEY];
[shareUserDefault setBool:YES forKey:@"FirstVoiceManagerProfile"];
}
- 讀取共享用戶偏好
// 獲取共享域的偏好設(shè)置
NSUserDefaults *shareUserDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.xxxx"];
// 解析推送自定義參數(shù)userInfo
NSDictionary *userInfo = [self dictionaryWithUserInfo:self.bestAttemptContent.userInfo];
BOOL canSound = [shareUserDefault boolForKey:OPEN_KEY];
NSString *voiceString = nil;
//
if (canSound && userInfo) {
voiceString = [NSString stringWithFormat:@"收款%@元!", userInfo[@"money"]];
}
線程安全
NSUserDefaults是線程安全的檐晕。