Objective c 使用NSUserDefaults保存数组

Objective c 使用NSUserDefaults保存数组,objective-c,arrays,plist,nsuserdefaults,Objective C,Arrays,Plist,Nsuserdefaults,我按照这个问题的答案将书签保存到NSUserDefaults中。它非常简单,并且在plist中没有条目时第一次正常工作。但随后它尝试将以前保存的书签复制到新的NSMutableArray中,应用程序崩溃: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSMutableArray initWithCapacity:]: method only define

我按照这个问题的答案将书签保存到NSUserDefaults中。它非常简单,并且在plist中没有条目时第一次正常工作。但随后它尝试将以前保存的书签复制到新的NSMutableArray中,应用程序崩溃:

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '*** -[NSMutableArray initWithCapacity:]: 
method only defined for abstract class.  Define -[__NSArrayM initWithCapacity:]!'
这是我稍加修改的代码:

-(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];

}

从NSUserDefaults返回的内容总是不可变的,不管它们在存储之前是否是可变的

初始容量:

仅在NSMutableArray上定义,而不在NSArray上定义

编辑: 看起来您也在两次初始化对象:

// 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];

从NSUserDefaults返回的内容总是不可变的,不管它们在存储之前是否是可变的

初始容量:

仅在NSMutableArray上定义,而不在NSArray上定义

编辑: 看起来您也在两次初始化对象:

// 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];
这是不正确的:

// Load your bookmarks (editable array)
NSMutableArray *bookmarks = [[NSMutableArray alloc]initWithCapacity:100]; // OK
NSArray *bookmarksLoaded = [userDefaults arrayForKey:[NSString stringWithFormat: @"favStationForService%@",userSelectedService]];
if (bookmarksLoaded != nil) {
    [bookmarks initWithArray:bookmarksLoaded]; // NOT AGAIN
} else {
    [bookmarks init]; // NOT AGAIN
}
不要对对象多次调用init方法。我怀疑这就是错误的根源,因为NSArray/NSMutableArray是作为类集群实现的,initWithCapacity:返回的确切类不是NSMutableArray,而是某个私有子类,它抱怨第二次被初始化。这里有一个更好的方法来实现同样的目标:

// Load your bookmarks (editable array)
NSMutableArray *bookmarks;
NSArray *bookmarksLoaded = [userDefaults arrayForKey:[NSString stringWithFormat: @"favStationForService%@",userSelectedService]];
if (bookmarksLoaded != nil) {
    bookmarks = [bookmarksLoaded mutableCopy];
} else {
    bookmarks = [[NSMutableArray alloc] initWithCapacity:100];
}
当您需要不可变容器对象的可变版本时,mutableCopy方法非常有用。请注意,由于copy位于方法名称中,因此您拥有结果,并且必须在以后释放它,除非您正在使用ARC或垃圾收集,并且不需要担心它。

这是不正确的:

// Load your bookmarks (editable array)
NSMutableArray *bookmarks = [[NSMutableArray alloc]initWithCapacity:100]; // OK
NSArray *bookmarksLoaded = [userDefaults arrayForKey:[NSString stringWithFormat: @"favStationForService%@",userSelectedService]];
if (bookmarksLoaded != nil) {
    [bookmarks initWithArray:bookmarksLoaded]; // NOT AGAIN
} else {
    [bookmarks init]; // NOT AGAIN
}
不要对对象多次调用init方法。我怀疑这就是错误的根源,因为NSArray/NSMutableArray是作为类集群实现的,initWithCapacity:返回的确切类不是NSMutableArray,而是某个私有子类,它抱怨第二次被初始化。这里有一个更好的方法来实现同样的目标:

// Load your bookmarks (editable array)
NSMutableArray *bookmarks;
NSArray *bookmarksLoaded = [userDefaults arrayForKey:[NSString stringWithFormat: @"favStationForService%@",userSelectedService]];
if (bookmarksLoaded != nil) {
    bookmarks = [bookmarksLoaded mutableCopy];
} else {
    bookmarks = [[NSMutableArray alloc] initWithCapacity:100];
}

当您需要不可变容器对象的可变版本时,mutableCopy方法非常有用。请注意,由于copy位于方法名称中,因此您拥有结果,并且必须在以后发布它,除非您使用ARC或垃圾收集,并且不需要担心它。

Ok,我将行更改为:NSMutableArray*bookmarks=[[NSMutableArray alloc]init];但仍然有相同的错误:/编辑了我的答案。您还初始化了两次对象。好的,我将行更改为:NSMutableArray*bookmarks=[[NSMutableArray alloc]init];但仍然有相同的错误:/编辑了我的答案。您还将初始化对象两次。