在 macOS 上會(huì)遇到一個(gè)問題:不同進(jìn)程之間共享 NSUserDefaults 的數(shù)據(jù)。
NSUserDefaults 里的數(shù)據(jù)本質(zhì)上就是一個(gè)設(shè)置 .plist 文件。
通常遇到這個(gè)問題的場景是:自己家的一組應(yīng)用想要共享一份兒 NSUserDefaults 數(shù)據(jù)。
解決思路利用 AppGroup 機(jī)制,如果應(yīng)用在沙盒狀態(tài)下需要在 project -> target -> Entitlement -> AppGroup 這里打開 AppGroup 設(shè)置,然后配置 AppGroup 的 ID.
這個(gè)解決方案是的本質(zhì)其實(shí)為同一個(gè)開發(fā) team 開發(fā)的多個(gè) app 設(shè)置了一個(gè) group containers,讓他們共享 group containers 的數(shù)據(jù),給這些 app 提供額外的進(jìn)程間通信機(jī)制??梢栽?~/Library/Group Containers/ 這兒看到這個(gè) Group Containers 的內(nèi)容。
我們的共享 NSUserDefauts 即是基于此技術(shù)支持的(如何配置 AppGroup 看后續(xù)說明)
* NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"DZQ5YNVEU2.com.frank”];
* [userDefaults setObject:@1 forKey:@"open"];
initWithSuiteName 的使用場景
- You can use this method when developing an app suite, to share preferences or other data among the apps,
- When developing an app extension, to share preferences or other data between the extension and its containing app.
然后我們?nèi)ス蚕淼?~/Library/Group Containers/DZQ5YNVEU2.com.frank/Library/Preferences/DZQ5YNVEU2.com.frank.plist 下看,發(fā)現(xiàn)已經(jīng)寫進(jìn)去了拿到共享的 userDefaults 文件

在另外一個(gè)配置了同樣的 AppGroup ID 的 application 中讀取 key 值 open ,能讀到剛剛的設(shè)置。說明可以進(jìn)行共享 NSUserDefaults。
可以通過 NSFileManager 的 API - NSURL *url = [fileman containerURLForSecurityApplicationGroupIdentifier:@“ DZQ5YNVEU2.com.frank”]; 來獲取該文件的路徑。
兩個(gè) QA:
Q: 這個(gè)共享的 UserDefaults 和應(yīng)用本身的 [[NSUserDefaults standardUserDefaults] 是啥關(guān)系?
A: 沒啥關(guān)系,因?yàn)檫@兩個(gè)底層的 .plist 文件位于不同的位置,你訪問的時(shí)候注意一下訪問的是哪個(gè)就好了。有必要和別人共享的就放到共享 UserDefaults 里,沒有就放到自己的 NSUserDefaults 里。
Q: 能通過 [[NSUserDefaults alloc] initWithSuiteName:@"DZQ5YNVEU2.com.frank”]; 這種方法來獲取其余你知道 Suite name 的應(yīng)用的 Preference list 嗎?
A: 我寫了 demo 試了試發(fā)現(xiàn)并不能。
initWithSuiteName 的官方說明 On macOS, specifying another app’s bundle identifier will get you that app’s preferences search list, unless prevented by the App Sandbox.
Adding an App to an App Group
The com.apple.security.application-groups (available in macOS v10.7.5 and v10.8.3 and later) allows multiple apps produced by a single development team to share access to a special group container. This container is intended for content that is not user-facing, such as shared caches or databases.
In addition, this attribute allows the apps within the group to share Mach and POSIX semaphores and to use certain other IPC mechanisms among the group’s members. For additional details and naming conventions, read “Mach IPC and POSIX Semaphores and Shared Memory” in App Sandbox Design Guide.
The value for this key must be of type array, and must contain one or more string values, each of which must consist of your development team ID, followed by a period, followed by an arbitrary name chosen by your development team. For example:
<key>com.apple.security.application-groups</key>
<array>
<string>DG29478A379Q6483R9214.HolstFirstAppSuite</string>
<string>DG29478A379Q6483R9214.HolstSecondAppSuite</string>
</array>
The group containers are automatically created or added into each app’s sandbox container as determined by the existence of these keys. The group containers are stored in ~/Library/Group Containers/<application-group-id>, where <application-group-id> is one of the strings from the array. Your app can obtain the path to the group containers by calling the containerURLForSecurityApplicationGroupIdentifier: method of NSFileManager.
Demo 地址: https://github.com/fanxiushan/Demo.FRShareUserDefaults
參考鏈接:
- https://developer.apple.com/documentation/foundation/nsuserdefaults/1409957-initwithsuitename
- https://developer.apple.com/documentation/foundation/nsfilemanager/1412643-containerurlforsecurityapplicati?language=objc#
- https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html
- https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19