The documentation doesn't specify if initWithArray: sends the objects in the old array (prefs) an additional retain when added to the new array (userAdded). It should, because the items are being added to the new array. Maybe when the old array (prefs) is deallocated, the retain count on the elements in userAdded drops too low, the objects are deallocated also, and the app crashes. To check this, I asked the contents of the first array for their retain count before and after calling initWithArray:.
NSUserDefaults *myDefault = [NSUserDefaults standardUserDefaults];
NSArray *prefs = [myDefault arrayForKey:@"addedPrefs"];
NSUInteger i, count = [prefs count];
for (i = 0; i < count; i++) {
NSObject * obj = [prefs objectAtIndex:i];
NSLog(@"Object: %@, Retain count: %d.", obj, [obj retainCount]);
}
userAdded = [[NSMutableArray alloc] initWithArray:prefs];
for (i = 0; i < count; i++) {
NSObject * obj = [prefs objectAtIndex:i];
NSLog(@"Object: %@, Retain count: %d.", obj, [obj retainCount]);
}
The objects report an increased retain count, so the prefs array can be released without affecting the new array. But running this code still leaks an NSArray.
So the problem must lie with the prefs array. Since the NSUserDelfaults method arrayForKey: produces the prefs array, yet the words "alloc", "new", or "copy" are not found in this method's name, the calling method does not own the prefs array. Most likely, the prefs array was added to an autorelease pool. To test this idea, I surrounded the above test code with calls to NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
and [pool drain]
. Running this code does not leak an array.
So I think the prefs array is being added to an autorelease pool that doesn't get drained. The simplest way to eliminate this leak would be to make an autorelease pool before creating the prefs array, and draining that pool when done with the prefs array.