NSUserDefaults problems

Discussion in 'Mac Programming' started by Soulstorm, Nov 22, 2007.

  1. macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #1
    I have two classes that look like this:
    Code:
    @interface ModStatus: NSObject <NSCoding>{
    	
    	NSMutableDictionary *properties;
    }
    
    - (void)setProperties:(NSDictionary *)otherProperties;
    - (NSMutableDictionary *)properties;
    
    @end
    @implementation ModStatus
    
    #pragma mark Inits, setters, getters
    
    - (id) init
    {
    	self = [super init];
    	if (self != nil) {
    		NSArray *values = [NSArray arrayWithObjects:@"modName", @"modLocation", @"preferenceFileLocation", @"isFirstTime",nil];
    		NSArray *keys = [NSArray arrayWithObjects:@"<not set>", @"<mod location not set>", @"<not set>", [NSNumber numberWithBool:YES], nil];
    		properties = [NSMutableDictionary dictionaryWithObjects:values forKeys:keys];
    	}
    	return self;
    }
    
    - (void)setProperties:(NSDictionary *)otherProperties
    {
    	[properties setDictionary:otherProperties];
    }
    
    - (NSMutableDictionary *)properties
    {
    	return properties;
    }
    
    #pragma mark NSCoding
    - (void)encodeWithCoder:(NSCoder *)coder
    {
    	//[coder encodeObject:properties forKey:@"properties"];
    }
    
    - (id)initWithCoder: (NSCoder *) coder
    {
    	//properties = [coder decodeObjectForKey:@"properties"];
    	return self;
    }
    
    #pragma mark dealloc
    - (void) dealloc
    {
    	[properties release];
    	[super dealloc];
    }
    
    @end
    
    
    
    
    
    @interface ModSelector : NSObject <NSCoding>{
    	NSMutableArray *modStatuses;
    	int SELECTED_MOD;
    }
    - (id) initWithStatuses :(NSArray *)statuses;
    - (void)changeSelectedMod:(int)newSelection;
    - (void)setModStatuses:(NSArray *)newModStatuses;
    - (ModStatus *)currentModStatus;
    - (ModStatus *)modStatusAtIndex:(unsigned)index;
    - (NSMutableArray *)modStatuses;
    - (unsigned)count;
    
    - (void)selectModWithName:(NSString *)name;
    - (id)valueForCurrentModKey: (id)key;
    @end
    
    
    @implementation ModSelector
    - (id) init
    {
    	self = [super init];
    	if (self != nil) {
    		ModStatus *status1 = [[[ModStatus alloc]init]autorelease];
    		ModStatus *status2 = [[[ModStatus alloc]init]autorelease];
    		[[status1 properties]setValue:@"FS2_Open" forKey:@"modName"];
    		[[status2 properties]setValue:@"BBTRL" forKey:@"modName"];
    		
    		modStatuses = [[NSMutableArray alloc]init];
    		
    		[modStatuses addObject:status1];
    		[modStatuses addObject:status2];
    		
    		SELECTED_MOD = FIRST_MOD;
    	}
    	return self;
    }
    
    - (id) initWithStatuses :(NSArray *)statuses
    {
    	self = [super init];
    	if (self != nil) {
    		modStatuses = [[NSMutableArray alloc]init];
    		[modStatuses setArray:statuses];
    	}
    	return self;
    }
    
    - (void)setModStatuses:(NSArray *)newModStatuses
    {
    	[modStatuses setArray:newModStatuses];
    }
    
    - (ModStatus *)currentModStatus
    {
    	return [modStatuses objectAtIndex:SELECTED_MOD];
    }
    
    -(void)selectModWithName:(NSString *)name
    {
    	int i;
    	for (i=0; i<[modStatuses count]; i++) {
    		//NSLog(@"ASD");
    		if ([name isEqualToString:[[[modStatuses objectAtIndex:i]properties]valueForKey:@"modName"]] == TRUE){
    			SELECTED_MOD = i;
    			break;
    		}
    	}
    }
    
    - (NSMutableArray *)modStatuses
    {
    	return modStatuses;
    }
    
    - (ModStatus *)modStatusAtIndex:(unsigned)index
    {
    	if ([self count] > index)
    		return [modStatuses objectAtIndex:index];
    	return nil;
    }
    
    - (void)changeSelectedMod:(int)newSelection
    {
    	SELECTED_MOD = newSelection;
    }
    
    #pragma mark Getting mod parameters
    
    - (id)valueForCurrentModKey: (id)key
    {
    	ModStatus *currentObject = [modStatuses objectAtIndex:SELECTED_MOD];
    	return [[currentObject properties]valueForKey:key];
    }
    
    - (unsigned)count
    {
    	return [modStatuses count];
    }
    
    #pragma mark NSCoding
    
    - (void)encodeWithCoder:(NSCoder *)coder
    {
    	[coder encodeObject:modStatuses forKey:@"modStatuses"];
    }
    
    - (id)initWithCoder: (NSCoder *) coder
    {
    	modStatuses = [coder decodeObjectForKey:@"modStatuses"];
    	return self;
    }
    
    #pragma mark dealloc
    - (void) dealloc
    {
    	[modStatuses release];
    	[super dealloc];
    }
    
    
    I build a Cocoa Application, and inside the -init function of one of the classes, I have the following lines of code:
    Code:
    NSMutableDictionary *prop = [NSMutableDictionary dictionary];
    prefs = [NSUserDefaults standardUserDefaults];
    ModSelector *ms = [[ModSelector alloc]init];
    [prop setObject:ms forKey:@"modSelector"];
    [prefs registerDefaults:prop];
    
    The application crashes and the debugger comes up at "[prefs registerDefaults:prop]" without telling me why. Can anyone help me with this?
     
  2. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
    From the docs:

    If you want to use your ModSelector object as a value in the user defaults, I'd suggest archiving it (using NSArchiver or NSKeyedArchiver).
     
  3. thread starter macrumors 68000

    Soulstorm

    Joined:
    Feb 1, 2005
    #3
    I tried that, and my application crashes at startup. here is the code:

    Code:
    @implementation GeneralHandler
    
    - (id) init
    {
    	self = [super init];
    	if (self != nil) {
    		
    		NSMutableDictionary *prop = [NSMutableDictionary dictionary];
    		
    		prefs = [NSUserDefaults standardUserDefaults];
    		ModSelector *ms = [[ModSelector alloc]init];
    		NSData *ModSelectorData = [NSKeyedArchiver archivedDataWithRootObject:ms];
    		[prop setObject:ModSelectorData forKey:@"ModSelectorData"];
    		[prop setObject:@"hello world" forKey:@"hello"];
    		[prefs registerDefaults:prop];
    		
    		//loading...
    		ModSelector *sel = [NSKeyedUnarchiver unarchiveObjectWithData:[prefs objectForKey:@"ModSelectorData"]];	
    		
    	}
    	return self;
    }
    
    
    ................ other code................
    @end
    
    return error:
    Code:
    [Session started at 2007-11-24 11:13:18 +0200.]
    multiplemodsupport 2(1516) malloc: *** error for object 0x156cf0: incorrect checksum for freed object - object was probably modified after being freed.
    *** set a breakpoint in malloc_error_break to debug
    Tried to locate the line that raises the error, and it is the line that unarchives the object from the preferences. Also, some lined like those:

    Code:
    NSData *writableData = [NSKeyedArchiver archivedDataWithRootObject:availableModSelector];
    	[prefs setObject:writableData forKey:@"ModSelectorData"];
    will also raise an exception, but the debugger won't tell me why this time. I don't know how to fix it. Anyone with a good idea? Does this have something to do with my encoding and decoding methods?
     
  4. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    Sounds like a memory management problem with your encodeWithCoder: method.

    Also be sure to release your ms object after adding it to the dictionary. You are leaking memory at this point (assuming you don't have GC enabled).
     

Share This Page