Re: A Mac App & helper NSStatusItem - how to share preferences
On Wed, Feb 11, 2009 at 5:55 AM, Trygve Inda wrote: > In my helper app I use: > > userDefaults = > [[NSUserDefaults standardUserDefaults] > persistentDomainForName:kMainAppIdent]; > > You just need to make sure there is no chance of the helper and the host > writing at the same time to the same file. Actually there is no such need. The user defaults system is smart about synchronizing simultaneous changes from multiple processes, and will do the right thing if both of your processes should hit the file at the same time. Mike ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
> Steve Cronin (steve_cro...@mac.com) on 2008-12-28 8:41 PM said: > >> I have an application which will have an optional helper NSStatusItem. >> The statusItem is a stand-alone application which can be installed as >> a LoginItem. >> >> I want this status item to be able to read the preferences file from >> the application. > > No need to drop to CFPreferences. Let's say your 2 bundle identifiers > are "com.cronin.mainapp" and "com.cronin.helper". > > In your helper app, just do this: > > NSUserDefaults* sud = [NSUserDefaults standardUserDefaults]; > [sud addSuiteNamed:@"com.cronin.mainapp"]; > > Sean In my helper app I use: userDefaults = [[NSUserDefaults standardUserDefaults] persistentDomainForName:kMainAppIdent]; You just need to make sure there is no chance of the helper and the host writing at the same time to the same file. Trygve ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
On Tue, Dec 30, 2008 at 8:18 PM, Steve Cronin wrote: > Michael; > > OK to really perhaps beat the poor horse, is the following kosher? > > (NSDictionary *) prefDictionary { >return [(NSDictionary *)CFPreferencesCopyMultiple(NULL, appBundleID, > kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) autorelease]; > } Yep, that's fine (as long as you're not using garbage collection) and also pretty. Well, as pretty as CF code gets, anyway. Mike ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
Steve Cronin (steve_cro...@mac.com) on 2008-12-28 8:41 PM said: >I have an application which will have an optional helper NSStatusItem. >The statusItem is a stand-alone application which can be installed as >a LoginItem. > >I want this status item to be able to read the preferences file from >the application. No need to drop to CFPreferences. Let's say your 2 bundle identifiers are "com.cronin.mainapp" and "com.cronin.helper". In your helper app, just do this: NSUserDefaults* sud = [NSUserDefaults standardUserDefaults]; [sud addSuiteNamed:@"com.cronin.mainapp"]; Sean ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
Michael; OK to really perhaps beat the poor horse, is the following kosher? (NSDictionary *) prefDictionary { return [(NSDictionary *)CFPreferencesCopyMultiple(NULL, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost) autorelease]; } Steve Michael said: Yep, this fixes the leak. Your Copy is balanced with a Release and all is well. However, just to be really nitpicky, I'll point out that it's a bit ugly. You build a new dictionary from the old one, then throw the old one away. Better to just keep the old one around with something like this: return [(id)prefs autorelease]; Or if you're in a garbage collected environment: return NSMakeCollectable(prefs); (And you can do both if you're writing dual-mode code.) ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
On Tue, Dec 30, 2008 at 4:14 PM, Steve Cronin wrote: > Michael - So does the revised code below fix the leak? > > After a bit more studying of the documentation, I offer these revised 'more > Cocoa-friendly' updates: > > The driving issue is a helper app which wants to access prefs written by the > 'motherApp'. > > - (NSDictionary *) prefDictionary { >CFStringRef appBundleID = (CFStringRef)motherAppBundleID; >//Core Foundation 'create rule' sez I own this -> I must dispose of > it (because 'copy' or 'create' in CF method name) >CFDictionaryRef prefs = CFPreferencesCopyMultiple(NULL, appBundleID, > kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); >//cast it into an auto-released Cocoa object >NSDictionary *result = [NSDictionary > dictionaryWithDictionary:(NSDictionary *)prefs]; >//take care of the low-level memory issue >CFRelease(prefs); >return result; > } Yep, this fixes the leak. Your Copy is balanced with a Release and all is well. However, just to be really nitpicky, I'll point out that it's a bit ugly. You build a new dictionary from the old one, then throw the old one away. Better to just keep the old one around with something like this: return [(id)prefs autorelease]; Or if you're in a garbage collected environment: return NSMakeCollectable(prefs); (And you can do both if you're writing dual-mode code.) Mike ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
Michael - So does the revised code below fix the leak? After a bit more studying of the documentation, I offer these revised 'more Cocoa-friendly' updates: The driving issue is a helper app which wants to access prefs written by the 'motherApp'. - (NSDictionary *) prefDictionary { CFStringRef appBundleID = (CFStringRef)motherAppBundleID; //Core Foundation 'create rule' sez I own this -> I must dispose of it (because 'copy' or 'create' in CF method name) CFDictionaryRef prefs = CFPreferencesCopyMultiple(NULL, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); //cast it into an auto-released Cocoa object NSDictionary *result = [NSDictionary dictionaryWithDictionary: (NSDictionary *)prefs]; //take care of the low-level memory issue CFRelease(prefs); return result; } It also may be worth pointing out that this dictionary only gets the values from the permanent store. So any registered defaults which the user has never changed do NOT show up in this dictionary. Now instead of using the low-level API to obtain individual values simply access key-value pairs using the NSDictionary returned above. This avoids having to write any further code to read motherApp's preferences. There are some stern words in the docs that weigh against indiscriminate accessing using the low-level stuff, so just get the dictionary and be done with it! Now if helper MUST update a motherApp preference: - (void) setPrefValue:(id)preferenceValue forKey:(NSString *)preferenceKey { CFStringRef appBundleID = (CFStringRef)motherAppBundleID; CFPreferencesSetValue((CFStringRef)preferenceKey, (CFPropertyListRef)preferenceValue, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); // as Jean-Daniel noted the line below is expensive and to be used only as required //that being said - it ain't on the disk until its on the disk CFPreferencesSynchronize(appBundleID, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); } NOTE: There is a CFPreferencesSetMultiple which allows for setting a dictionary's worth of keys at once as well as specifying an array of keys to be removed. You still have to use CSPreferencesSynchronize if you want to get it written I hope this is useful. Steve ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
Le 30 déc. 08 à 14:37, Michael Ash a écrit : On Mon, Dec 29, 2008 at 4:16 AM, Steve Cronin wrote: Kyle; Thanks for that pointer! Based on the documentation you cited I've now got the reading of NSUserDefaults functioning! In the hopes that it might be useful to someone else, I include these 'Cocoa friendly' methods. I grant that there are some improvements which could be made, I include them here in the spirit of helpfulness to the community // myBundleID is a static string defined elsewhere //retrieves the full user defaults dictionary - (NSDictionary *) prefDictionary { CFStringRef appBundleID = (CFStringRef)myBundleID; return (NSDictionary *)CFPreferencesCopyMultiple(NULL, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } Note that this returns a retained object and thus violates Cocoa memory management guidelines. This is OK if the code calling it knows this and releases it, but since it probably doesn't then this will cause a leak every time it's called. And it's much better to fix this up to autorelease the dictionary when returning it than to patch up the caller to do so. //retrieves the string Value of a key [full implementation of all the CFPropertyList types is left as an exercise for the reader) - (NSString *) prefStringValueforKey:(NSString *)preferenceKey { CFStringRef appBundleID = (CFStringRef)myBundleID; return (NSString*)CFPreferencesCopyValue((CFStringRef)preferenceKey, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } Rather than a full implementation of all the types, why not just a single method which returns id? Note that you get no real type safety here because the cast to NSString* will succeed even if the actual value is a number, dictionary, array, or date. //sets the value for a key - (void) setPrefValue:(id)preferenceValue forKey:(NSString *)preferenceKey { CFStringRef appBundleID = (CFStringRef)myBundleID; CFPreferencesSetValue((CFStringRef)preferenceKey, (CFPropertyListRef)preferenceValue, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); CFPreferencesSynchronize(appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } No comment here! Just a little comment here (from the Preferences Best Practices) - Only synchronize when absolutely necessary You may have a valid reason to sync at each write, but have a look at the "Synchronizing Preferences Across Process Boundaries" section for more infos. http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFPreferences/Concepts/BestPractices.html ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
On Mon, Dec 29, 2008 at 4:16 AM, Steve Cronin wrote: > Kyle; > > Thanks for that pointer! Based on the documentation you cited I've now got > the reading of NSUserDefaults functioning! > > In the hopes that it might be useful to someone else, I include these 'Cocoa > friendly' methods. > I grant that there are some improvements which could be made, I include them > here in the spirit of helpfulness to the community > // myBundleID is a static string defined elsewhere > > //retrieves the full user defaults dictionary > - (NSDictionary *) prefDictionary { >CFStringRef appBundleID = (CFStringRef)myBundleID; >return (NSDictionary *)CFPreferencesCopyMultiple(NULL, appBundleID, > kCFPreferencesCurrentUser, kCFPreferencesAnyHost); > } Note that this returns a retained object and thus violates Cocoa memory management guidelines. This is OK if the code calling it knows this and releases it, but since it probably doesn't then this will cause a leak every time it's called. And it's much better to fix this up to autorelease the dictionary when returning it than to patch up the caller to do so. > //retrieves the string Value of a key [full implementation of all the > CFPropertyList types is left as an exercise for the reader) > - (NSString *) prefStringValueforKey:(NSString *)preferenceKey { >CFStringRef appBundleID = (CFStringRef)myBundleID; >return (NSString*)CFPreferencesCopyValue((CFStringRef)preferenceKey, > appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); > } Rather than a full implementation of all the types, why not just a single method which returns id? Note that you get no real type safety here because the cast to NSString* will succeed even if the actual value is a number, dictionary, array, or date. > //sets the value for a key > - (void) setPrefValue:(id)preferenceValue forKey:(NSString *)preferenceKey { >CFStringRef appBundleID = (CFStringRef)myBundleID; >CFPreferencesSetValue((CFStringRef)preferenceKey, > (CFPropertyListRef)preferenceValue, appBundleID, > kCFPreferencesCurrentUser, kCFPreferencesAnyHost); >CFPreferencesSynchronize(appBundleID, kCFPreferencesCurrentUser, > kCFPreferencesAnyHost); > } No comment here! Mike ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
Kyle; Thanks for that pointer! Based on the documentation you cited I've now got the reading of NSUserDefaults functioning! In the hopes that it might be useful to someone else, I include these 'Cocoa friendly' methods. I grant that there are some improvements which could be made, I include them here in the spirit of helpfulness to the community // myBundleID is a static string defined elsewhere //retrieves the full user defaults dictionary - (NSDictionary *) prefDictionary { CFStringRef appBundleID = (CFStringRef)myBundleID; return (NSDictionary *)CFPreferencesCopyMultiple(NULL, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } //retrieves the string Value of a key [full implementation of all the CFPropertyList types is left as an exercise for the reader) - (NSString *) prefStringValueforKey:(NSString *)preferenceKey { CFStringRef appBundleID = (CFStringRef)myBundleID; return (NSString*)CFPreferencesCopyValue((CFStringRef)preferenceKey, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } //sets the value for a key - (void) setPrefValue:(id)preferenceValue forKey:(NSString *)preferenceKey { CFStringRef appBundleID = (CFStringRef)myBundleID; CFPreferencesSetValue((CFStringRef)preferenceKey, (CFPropertyListRef)preferenceValue, appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); CFPreferencesSynchronize(appBundleID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); } Steve On Dec 28, 2008, at 8:17 PM, Kyle Sluder wrote: On Sun, Dec 28, 2008 at 8:41 PM, Steve Cronin wrote: This not a managed environment nor is this issue related to users or hosts, so it doesn't seem that CFPreferences is called for (or even helps!) In fact, CFPreferences is exactly what you need. Apple has some sample code describing how to do exactly what you want: http://developer.apple.com/documentation/CoreFOundation/Conceptual/CFPreferences/Tasks/UsingLowAPI.html#/ /apple_ref/doc/uid/20001170 --Kyle Sluder ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: A Mac App & helper NSStatusItem - how to share preferences
On Sun, Dec 28, 2008 at 8:41 PM, Steve Cronin wrote: > This not a managed environment nor is this issue related to users or hosts, > so it doesn't seem that CFPreferences is called for (or even helps!) In fact, CFPreferences is exactly what you need. Apple has some sample code describing how to do exactly what you want: http://developer.apple.com/documentation/CoreFOundation/Conceptual/CFPreferences/Tasks/UsingLowAPI.html#//apple_ref/doc/uid/20001170 --Kyle Sluder ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
A Mac App & helper NSStatusItem - how to share preferences
Folks; I have an application which will have an optional helper NSStatusItem. The statusItem is a stand-alone application which can be installed as a LoginItem. I want this status item to be able to read the preferences file from the application. The user sets a number of preferences in the normal app which influence both how the app and the status item should behave. I'm under the clear impression that I should not use the same bundleIdentifer for the application and the statusItem. They could both be running at the same time... Yet the bundleIdentifier seems to be the key to the file that [NSUserDefaults sharedDefaults] opens.. This not a managed environment nor is this issue related to users or hosts, so it doesn't seem that CFPreferences is called for (or even helps!) How can I get the statusItem to read the application's preferences? Thanks! Steve ___ 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com