因?yàn)轫?xiàng)目里面有個(gè)切換環(huán)境
的功能轩触,切換環(huán)境
后就會(huì)將選中的環(huán)境更新到用戶偏好
里面萍鲸,然后退出app
邢疙,重新啟動(dòng)app
就從用戶偏好里面讀取新的環(huán)境變量
肮柜,然后請(qǐng)求的新環(huán)境地址
陷舅。
之前代碼類似如下:
[FJFEnvironmentManager updateEnvironmentType:type];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
exit(0);
});
+ (void)updateEnvironmentType:(FJFEnvironmentType)environmentType {
[NSUserDefaults.standardUserDefaults setValue:@(environmentType) forKey:kFJJEnvironmentTypeKey];
[NSUserDefaults.standardUserDefaults synchronize];
}
但存在有時(shí)候切換環(huán)境不成功問題,終于找到原因审洞。
分析過(guò)程
首先從代碼邏輯分析莱睁,覺得應(yīng)該是沒問題的,因?yàn)楦颅h(huán)境并保存到偏好設(shè)置芒澜,這里調(diào)用了[NSUserDefaults.standardUserDefaults synchronize];
同步方法仰剿,因此應(yīng)該是不存在環(huán)境沒更新的問題。
接著通過(guò)查看偏好設(shè)置的plist
文件痴晦,發(fā)現(xiàn)環(huán)境的更改并沒有即時(shí)南吮,存在延期情況,因此查看了synchronize
函數(shù)誊酌。
/*!
-synchronize is deprecated and will be marked with the API_DEPRECATED macro in a future release.
-synchronize blocks the calling thread until all in-progress set operations have completed. This is no longer necessary. Replacements for previous uses of -synchronize depend on what the intent of calling synchronize was. If you synchronized...
- ...before reading in order to fetch updated values: remove the synchronize call
- ...after writing in order to notify another program to read: the other program can use KVO to observe the default without needing to notify
- ...before exiting in a non-app (command line tool, agent, or daemon) process: call CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication)
- ...for any other reason: remove the synchronize call
*/
這里說(shuō)synchronize
這個(gè)函數(shù)已經(jīng)被棄用部凑,在將來(lái)版本使用中將使用API_DEPRECATED
宏進(jìn)行標(biāo)志。
也就是說(shuō)用戶偏好的同步函數(shù)synchronize
不在是同步阻塞的术辐,而是系統(tǒng)內(nèi)部定期去更新保存的砚尽。
用戶偏好本質(zhì)是一個(gè)plist
文件,之所以多封裝了一層辉词,是因?yàn)槎嗉恿艘粚觾?nèi)存緩存操作必孤,你對(duì)用戶偏好的修改,會(huì)直接更新到內(nèi)存緩存中瑞躺,然后你立刻去讀取敷搪,會(huì)直接從內(nèi)存緩存中返回,然后內(nèi)部在定時(shí)存儲(chǔ)到plist
里面幢哨。
也正是因?yàn)檫@樣赡勘,我們更換環(huán)境,退出app捞镰,然后立刻重啟闸与,可能用戶偏好的plist
還沒更新毙替,導(dǎo)致讀取到的還是以前的環(huán)境變量值。
修改方法
最開始的時(shí)候想直接新建一個(gè)
plist
類來(lái)存儲(chǔ)環(huán)境變量的值践樱,然后操作plist文件來(lái)修改環(huán)境變量的值厂画,但這種方法一來(lái)改動(dòng)量有點(diǎn)大,二來(lái)用plist
只存儲(chǔ)一個(gè)環(huán)境變量有點(diǎn)浪費(fèi)最終改用
NSKeyedArchiver歸檔
來(lái)存儲(chǔ)環(huán)境變量值拷邢,這樣只需新增路徑袱院,改變下存儲(chǔ)和讀取方法。