CocoaDev

Edit AllPages

Hi There,

I’m getting a BAD_ACCESS crash when I try and put an object into my ScreenSaverDefaults. I get the feeling its a problem with the way I’ve been retaining objects and such. Here’s what I’ve done: I created a “Friend” object, as show here.

@interface Friend : NSObject { NSString *firstName; NSString *lastName; NSString *uid; NSNumber *active; float result; }

-(id)init;

@implementation Friend

-(id)init { self = [super init]; return self; }

-(NSString *)name { NSMutableString *Name = [[[NSMutableString alloc] initWithString:@””] autorelease]; NSArray *Arguments = [NSArray arrayWithObjects:[self firstName], [self lastName], nil]; [Name appendString:[Arguments componentsJoinedByString:@” “]]; return Name; }

-(void)setFirstName:(NSString *)aFirstName { aFirstName = [aFirstName copy]; [aFirstName release]; firstName = aFirstName; }

-(NSString *)firstName { return firstName; }

/// and so forth for the other implementation methods

Then, I parse some xml of friends, and create a Mutable Array of friend objects. Check it out below. The code loops through the friend nodes of the xml, creates a friend object, and then adds it to the array..

// friends array has already been created when I init the screensaver… friends = [[NSMutableArray alloc] initWithCapacity:100];

// when i call the getFriends method…

for (i = 0; i < tokenXML rootElement] childCount]; i++) {

aNode = [[tokenXML rootElement] childAtIndex: i];

Friend *tempFriend = [[Friend alloc] init];

// ok, now loop through nodes
for (i2=0; i2 < [aNode childCount]; i2++) {
	
	// create a friend object
	
	
	
	
	
	
	if ([[[aNode childAtIndex:i2] name] isEqualTo:@"first_name"]) {
		/// add to object
		
		[[NSString* tempString = [[NSString alloc] initWithString:aNode childAtIndex:i2] stringValue;
		
		[tempFriend setFirstName: [tempString retain]];
		
		[tempString release];
		
		}
	
	if ([aNode childAtIndex:i2] name] isEqualTo:@"last_name"]) {
		/// add to object
		
		[[NSString* tempString = [[NSString alloc] initWithString:aNode childAtIndex:i2] stringValue;
		
		[tempFriend setLastName: [tempString retain]];
		
		[tempString release];
		
		}
		
	if ([aNode childAtIndex:i2] name] isEqualTo:@"uid"]) {
		/// add to object
		
		[[NSString* tempString = [[NSString alloc] initWithString:aNode childAtIndex:i2] stringValue;
		
		[tempFriend setUid: [tempString retain]];
		
		[tempString release];

		
		}
	int tempInt;
	tempInt = 0;
	[tempFriend setActive:[NSNumber numberWithInt:tempInt]];
	
	
	
	
	
	}

// ok, now check if we already have this friend
BOOL hasFriend;
hasFriend = NO;
for (i3 = 0; i3 < [friends count]; i3++) {
	if ([friends objectAtIndex:i3] uid] isEqualToString: [tempFriend uid) {
		// we already have it
		hasFriend = YES;
		}
	}

if (hasFriend == NO) {
	
	// add it to the friends array
	[friends addObject: [tempFriend retain]];
	}

[tempFriend release];


}

Then I do some sorting…

lastNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@”lastName”

								ascending:YES
								selector:@selector(caseInsensitiveCompare:)] autorelease];

sortDescriptors=[NSArray arrayWithObject:lastNameDescriptor];

sortedArray=friends sortedArrayUsingDescriptors:sortDescriptors] retain];

[friends release];

friends = [[[[NSMutableArray alloc] initWithArray: sortedArray];

Then, after all that, I try to add the friends array to the defaults, and that’s where I get the crash:

[defaults setObject:friends forKey:@”friends”]; [defaults synchronize];

Anyways, I really feel like it has something to do with the way I’m retaining objects and such. Any ideas?

Thanks, Alexandre


Your crash is almost certainly due to a MemoryManagement problem, your code is full of leaks and it wouldn’t surprise me if there were over-releases too. Read up on MemoryManagement and fix your code, and if you need help finding the specific object that’s being over-released then look up NSZombieEnabled.


Could you give any specific examples as to where I have gone wrong. Unfortunately it’s difficult for me to debug as it’s a ScreenSaver - NSZombieEnabled doesn’t appear to work.


Yes, your retains and release aren’t balanced. For example, you have a bunch of lines like [tempFriend setUid: [tempString retain]] and they will all cause a leak.

NSZombieEnabled will work if you create a custom executable in your project and set it to System Preferences, or better yet to SaverLab.

Update: whups, I was wrong. You do indeed have a lot of MemoryManagement errors but they aren’t causing your problem here. Your problem is that user defaults can only contain PropertyList objects, and you’re trying to store a bunch of custom classes in it.


Ok, thanks..

So basically I can only store Arrays in NSUserDefaults, or dictionaries… Is that correct? (At least for the kinda of structured data I’m trying to store). Can I have an array of Dictionary Objects?


The PropertyList page has been updated with a comprehensive list of allowed data types and links to more information.