PDA

View Full Version : NSArrayController, setContent, AwakeFromNib, and changes




BollywooD
Apr 15, 2009, 02:19 AM
I am building a plugin, and have saved some strings to userdefaults (from a NSTableView) like so:

NSArray * myArray = [self myArrayController];
[[MyPreferences userDefaults] setObject: myArray forKey:aKey];
[[MyPreferences userDefaults] synchronize];

which works great.

I would like to reload the strings back into my ArrayController on launching my app. I tried the following function, but It doesnt work?

- (void) awakeFromNib
{
NSArray * myArray = [[MyPreferences userDefaults] objectForKey:aKey];
[myArrayController setContent:myArray];
}


I also have another question: I would like to update my defaults each time the table is altered. is there an NSNotification I can use to monitor when the NSTableView is altered?

thanks, in advance



kainjow
Apr 15, 2009, 08:00 AM
This is probably the same underlining bug as in the other thread with loading the tab state. Can you post your custom preferences class? Most likely the bug is in there.

BollywooD
Apr 15, 2009, 04:01 PM
This is probably the same underlining bug as in the other thread with loading the tab state. Can you post your custom preferences class? Most likely the bug is in there.

heres the class, SCPreferences:
@implementation SCPreferences

+ sharedPreferences {
static BOOL preferencesAdded = NO;
id preferences = [super sharedPreferences];

if (preferences != nil && !preferencesAdded) {
[preferences addPreferenceNamed:@"Cookies" owner:[SCPreferencesModule sharedInstance]];
preferencesAdded = YES;
}

return preferences;
}

+ (void) setupUserDefaults
{
NSUserDefaults * ud = [[BundleUserDefaults alloc] initWithPersistentDomainName:SCPreferencesDomainNameKey];

[[NSUserDefaultsController sharedUserDefaultsController] _setDefaults:ud];

NSDictionary * appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:SCCookieAcceptPolicySafariBehavior], SCPreferencesCookieAcceptPolicy,
nil];
[ud registerDefaults:appDefaults];
// [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:appDefaults];

[ud release];
}


+ (NSUserDefaults *) userDefaults
{
return [[NSUserDefaultsController sharedUserDefaultsController] defaults];
}

@end

BollywooD
Apr 15, 2009, 09:34 PM
OK, I got the tabstate saving/reloading by:
calling the function elsewhere in the code ... I dont think the tabView had initialized, when i was calling the function.

I have tried moving the ArrayController setContent function elsewhere, but all it does, is crash the plugin?
:confused:

kainjow
Apr 16, 2009, 11:25 AM
I would do one of two things: use the normal [NSUserDefaults standardUserDefaults] and just give your preference keys a prefix unique to your app (e.g. SC__SomeValue) so that you don't conflict with Safari, or rewrite your class to use the CFPreferences API which can read/write from different domains without using private methods.

BollywooD
Apr 16, 2009, 05:20 PM
I figured out the problem....

Duh....

I was storing the array as NSStrings, and trying to read back into the ArrayController, as strings. as soon as i changed it back to saving as an array of NSDictionary items - everything worked as expected.

for simplicity though, I would like to keep the array, stored, as an array of NSStrings.
which leads me to my next question, how do I convert an array of NSStrings, into an array of NSDictionary items?

i have found this method:
propertyListFromStringsFileFormat

but are not exactly sure how to convert an entire array?
:confused:

kainjow
Apr 16, 2009, 05:39 PM
Well you will have to decide what 'key' is for each item, but something like this:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (NSString *str in array)
[dict setObject:str forKey:key];

BollywooD
Apr 16, 2009, 06:27 PM
Well you will have to decide what 'key' is for each item, but something like this:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
for (NSString *str in array)
[dict setObject:str forKey:key];

this converts fine, but I can only save multiple instances of the last entered domain?

heres the code im using:
- (NSArray *) convertStringsToDictionary
{
NSArray * blacklist = [[SCPreferences userDefaults] objectForKey:SCPreferencesKey];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSMutableArray * blacklistDomains = [NSMutableArray array];
NSEnumerator * enumerator = [blacklist objectEnumerator];
id node;
while ((node = [enumerator nextObject]))
{
for (NSString *str in blacklist)
[dict setObject:str forKey:@"blacklist"];
[blacklistDomains addObject:dict];
}
return blacklistDomains;
}

kainjow
Apr 16, 2009, 06:39 PM
Not sure what you're trying to do there, but you're looping through the entire array every time you loop through it with the enumerator. Either use the enumerator, or use the for loop, but not both.

The for loop is basically a better version of the enumerator and only is available in 10.5+, so you should use that whenever you can instead of the enumerator because it's faster and requires less code. But know that they both do the same thing, just different implementations.

BollywooD
Apr 16, 2009, 06:55 PM
:o
I am now using the following code.
if for example i have 4 strings, in my array, this code returns an array of 4 dictionary items (but the last entered string - 4X)?

am i doing something wrong?

- (NSArray *) convertStringsToDictionary
{
NSArray * blacklist = [[SCPreferences userDefaults] objectForKey:SCPreferencesBlacklistDomainsKey];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSMutableArray * blacklistDomains = [NSMutableArray array];
for (NSString *str in blacklist)
{
[dict setObject:str forKey:@"blacklist"];
[blacklistDomains addObject:dict];
}
return blacklistDomains;
}

kainjow
Apr 16, 2009, 07:21 PM
Your code is adding the same dictionary multiple times into the array, and each time is overwriting the previous blacklist object.

Are you trying to create an array of dictionaries, with each dictionary containing one key/value pair? If so, maybe this is what you want:

- (NSArray *) convertStringsToDictionary
{
NSArray * blacklist = [[SCPreferences userDefaults] objectForKey:SCPreferencesBlacklistDomainsKey];
NSMutableArray * blacklistDomains = [NSMutableArray array];
for (NSString *str in blacklist)
{
NSDictionary *dict = [NSDictionary dictionaryWithObject:str forKey:@"blacklist"];
[blacklistDomains addObject:dict];
}
return blacklistDomains;
}

BollywooD
Apr 16, 2009, 07:33 PM
thanks kainjow,

that works perfectly!
:D