NSArrayController, setContent, AwakeFromNib, and changes

Discussion in 'Mac Programming' started by BollywooD, Apr 15, 2009.

  1. macrumors 6502

    #1
    I am building a plugin, and have saved some strings to userdefaults (from a NSTableView) like so:

    Code:
    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?

    Code:
    - (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
     
  2. Moderator emeritus

    kainjow

    #2
    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.
     
  3. macrumors 6502

    #3
    heres the class, SCPreferences:
    Code:
    @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
     
  4. macrumors 6502

    #4
    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:
     
  5. Moderator emeritus

    kainjow

    #5
    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.
     
  6. macrumors 6502

    #6
    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:
     
  7. Moderator emeritus

    kainjow

    #7
    Well you will have to decide what 'key' is for each item, but something like this:
    Code:
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    for (NSString *str in array)
        [dict setObject:str forKey:key];
     
  8. macrumors 6502

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

    heres the code im using:
    Code:
    - (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;
    }
    
     
  9. Moderator emeritus

    kainjow

    #9
    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.
     
  10. macrumors 6502

    #10
    :eek:
    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?

    Code:
    - (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;
    }
     
  11. Moderator emeritus

    kainjow

    #11
    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:

    Code:
    - (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;
    }
     
  12. macrumors 6502

    #12
    thanks kainjow,

    that works perfectly!
    :D
     

Share This Page