I was following the answer for this question (How To Save Data For Bookmarks?) to save a bookmarks into the NSUserDefaults. It is pretty straightforward, and it works properly for the first time (when there’s no entry in the plist). But then it tries to copy the previously saved bookmarks into the new NSMutableArray the app crashes:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '*** -[NSMutableArray initWithCapacity:]:
method only defined for abstract class. Define -[__NSArrayM initWithCapacity:]!'
This is my code (a little modified):
-(void) addStationToFavorites{
// Get the user defaults object
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *userSelectedService = [userDefaults objectForKey:@"idBikeServiceProvider"];
// Load your bookmarks (editable array)
NSMutableArray *bookmarks = [[NSMutableArray alloc] initWithCapacity:100];
NSArray *bookmarksLoaded = [userDefaults arrayForKey:[NSString stringWithFormat: @"favStationForService%@",userSelectedService]];
if (bookmarksLoaded != nil) {
[bookmarks initWithArray:bookmarksLoaded];
} else {
[bookmarks init];
}
// Add a bookmark
NSMutableDictionary *bookmark = [NSMutableDictionary new];
[bookmark setValue:pass_stationName forKey:pass_stationId];
[bookmarks addObject:bookmark];
// Save your (updated) bookmarks
[userDefaults setObject:bookmarks forKey:[NSString stringWithFormat: @"favStationForService%@",userSelectedService]];
[userDefaults synchronize];
// Memory cleanup
[bookmarks release];
//Show feedback
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
message:@"Added!"
delegate:self
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
This is incorrect:
Don’t call an
initmethod more than once on an object. I suspect that is the source of your error, as NSArray/NSMutableArray is implemented as a “class cluster” and the exact class that is returned by theinitWithCapacity:is notNSMutableArray, but rather some private subclass, which is complaining about being init’d a second time. Here’s a better way to accomplish the same:The
mutableCopymethod is very useful when you need a mutable version of an immutable container object. Note that, since “copy” is in the method name, you own the result and must release it later (unless you’re using ARC or Garbage Collection and don’t need to worry about it).