Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
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?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
From the docs:

A default’s value can be only property list objects: NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary.

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

Soulstorm

macrumors 68000
Original poster
Feb 1, 2005
1,887
1
If you want to use your ModSelector object as a value in the user defaults, I'd suggest archiving it (using NSArchiver or NSKeyedArchiver).

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?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
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).
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.