假设我们的测试bundleID 为
com.ms.test
一、关闭沙盒模式下
偏好设置数据地址:
~/Library/Preferences/com.ms.test
如果删掉这个 plist 文件,依旧可以读出相应数据;(重启之后如何?亲们可以尝试)
这个情况下,执行下面命令可以解决:
killall -SIGTERM cfprefsd
二、沙盒模式下
偏好设置文件保存地址:
~/Library/Containers/com.ms.test/Data/Library/Preferences/com.ms.test
如果删掉 plist 文件,不会再自动生成 plist(即使clean build folder 和删掉 Containers 内对应的文件夹)。这时还是可以读取数据,但写入数据会报下述错误:
[User Defaults] Couldn’t read values in CFPrefsPlistSource<0x6040000e1980> (Domain: com.ms.test, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: Yes): accessing preferences outside an application’s container requires user-preference-read or file-read-data sandbox access, detaching from cfprefsd
[User Defaults] attempt to set 123 for key in key in non-persistent preferences domain CFPrefsPlistSource<0x6040000e1980> (Domain: com.ms.test, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: Yes)
这时你可能会想到去沙盒开启 user-preference-read
和 file-read-data
权限。但是,没有这两个权限。
原因:本质还是因为缺失 plist 造成。
解决方法:在终端输入 $ killall -SIGTERM cfprefsd
;然后重新 build,就会再次生成 plist 文件。不需要开任何权限。
三、关于 cfprefsd
此时你可能和我一样,好奇在删除plist 之后,app 是去哪里获取的数据;也好奇 cfprefsd 是何方神圣。也许他们之前有关联。
cfprefsd
这个名字,让人联想到 CFPreference,尾部的d
像是一个守护进程 daemon 名字。
打开活动监视器,确是有这个进程的存在。
它的执行地址位于 /usr/sbin/cfprefsd
。
使用 $ killall -SIGTERM cfprefsd
命令后,第三个(用户级的 )cfprefsd 被杀掉,2s 后重启了(PID 变化了)。
前面两个是更深的守护?
猜想执行命令后,让之前的缓存数据被清理了。
看到这篇文章:What Is cfprefsd, and Why Is It Running on my Mac? 明确了我的想法。
通过 man cfprefsd
查看 cfprefsd 的使用手册,会得到这样一段话
cfprefsd provides preferences services for the CFPreferences and NSUserDefaults APIs.There are no configuration options to cfprefsd manually.
cfprefsd 这个守护进程给 CFPreferences 和 NSUserDefaults APIs 提供偏好设置服务。没有手动配置选项。