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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to