Re: Application Suite Preferences
Re: Application Suite Preferences
- Subject: Re: Application Suite Preferences
- From: Seth Willits <email@hidden>
- Date: Mon, 27 Feb 2012 17:59:54 -0800
On Feb 27, 2012, at 2:24 AM, Bill Cheeseman wrote:
>> At any rate, I'm interested in hearing the thoughts of anyone who really knows how these suite preferences should be used.
>
> My UI Actions product <http://pfiddlesoft.com/uiactions> does it exactly the way you describe, in every particular. I wrote the first version in 2004, before bindings were available, and there has been no reason to rewrite it to try to use bindings. It works just fine.
Thanks. That at least provides some validation.
So I've been experimenting a variety of solutions, and I'm currently sitting with this and thinking about it:
https://gist.github.com/49d57bd0a61bb5e40d2d
Basically, I use a method implementation swizzle to make [NSUserDefaults standardUserDefaults] return an instance of my AGUserDefaults subclass. That allows me to override addSuite: removeSuite: and setObject:forKey: to do some things.
First, when a suite is added, the UD registers as an observer for distributed notifications using that suite name. Whenever a change is made to the suite via setObject:forKey:inSuite:, the notification is posted so other suite members will know the suite changed.
That alone works for factored-out suite preferences. That is, apps A (com.me.a) and B (com.me.b) use a "com.me.sharedSuite" domain for shared prefs.
In one of my particular cases however, I really just have a background tool which I want to be able to easily read the main application's preferences. The background tool is always running however, so it needs to track changes to the main applications preferences *live*, not just at launch. Since the background tool does not have preferences of its own, a shared suite domain separate from the main application domain doesn't make sense.
So to enable the application's domain to be a "suite" domain to the background tool, I have some special handling of the "suite" with the same name as the running application's identifier. This special handling includes overriding setObject:forKey: and removeObjectForKey: to post a suite change notification so that the background tool can watch changes to the main application's domain.
Since AGUserDefaults automatically forces itself to be used instead of NSUserDefaults (when calling [NSUserDefaults standardUserDefaults], if I include AGUserDefaults in shared framework, then all of my apps would start posting distributed notifications for suite changes when the main app's domain is changed. To prevent that, the posting of suite changes for the app's domain only happens if the application domain is registered as a suite itself via addSuite:. (This also allows it to receive changes notifications if the background tool decided to change a main app preference.)
Lastly, it's experimental and commented out in the code at the link above, but in the override for setObject:forKey: I added a little bit of logic which makes binding to a suite work implicitly. What happens is if NSUserDefaults' setObject:forKey: method is called and the key does not exist in the application domain, then it checks all of the suites. If a suite contains that key, then the object value is stored in the suite domain rather than the application domain. This lets you hook up bindings with NSUserDefaultsController to a suite; The one thing I haven't yet solved to complete bindings support, is that I need to add code which in the notification for a suite change, will inspect the current in-memory suite values, load the new values from the disk, find the ones that change, and post KVO notifications for them so the bindings controller will pick up on it and display the new values. That's actually a little more involved since I would need to maintain my own in-memory dictionary for each domain since there's no way to grab the in-memory values for a particular domain, only the on-disk ones.
Anyway, bindings experiment stuff aside, overall I think this works well. It basically "just happens" and seems to work fine.
--
Seth Willits
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden