我想在我的RSS阅读器中创建一个“收藏夹”。我的RSS解析器正在解析NSMutableArray的RSS提要,然后从我的部分rss(选定的帖子)创建对象“item”。 我的代码:
//Creating mutable array and adding items:
- (void)viewDidLoad {
if (favoritedAlready == nil) {
favoritedAlready = [[NSMutableArray alloc] init];
[[NSUserDefaults standardUserDefaults] setObject:favoritedAlready forKey:@"favorites"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(@"избранное с нуля");
}
}
- (void) addToFavorites {
NSMutableArray* favoritedAlready = [[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"];
[favoritedAlready addObject: item];
[[NSUserDefaults standardUserDefaults] setObject:favoritedAlready forKey:@"favorites"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(@"Добавлено в избранное. В избранном %i статей", [favoritedAlready count]);
}
//Removing items (another View)
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
rssItems = [[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"];
[self.tableView reloadData];
NSLog(@"Загрузилось избранное, %i избранных статей", [rssItems count]);
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"Номерок строчки в которой удаляемый объект %i", indexPath.row+1);
[rssItems removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[[NSUserDefaults standardUserDefaults] setObject:rssItems forKey:@"favorites"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
最初效果很好,但是当我添加和删除项目时,它开始崩溃。 崩溃日志: 我将对象添加到收藏夹并将其删除:
2011-09-25 20:14:44.534 ARSSReader[36211:11303] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'
*** Call stack at first throw:
(
0 CoreFoundation 0x015505a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x016a4313 objc_exception_throw + 44
2 CoreFoundation 0x01508ef8 +[NSException raise:format:arguments:] + 136
3 CoreFoundation 0x01508e6a +[NSException raise:format:] + 58
4 CoreFoundation 0x01547dd1 -[__NSCFArray removeObjectAtIndex:] + 193
5 ARSSReader 0x000a0ced -[FavoritesView tableView:commitEditingStyle:forRowAtIndexPath:] + 173
6 UIKit 0x00876037 -[UITableView(UITableViewInternal) animateDeletionOfRowWithCell:] + 101
7 UIKit 0x0080b4fd -[UIApplication sendAction:to:from:forEvent:] + 119
8 UIKit 0x0089b799 -[UIControl sendAction:to:forEvent:] + 67
9 UIKit 0x0089dc2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
10 UIKit 0x0089c7d8 -[UIControl touchesEnded:withEvent:] + 458
11 UIKit 0x0082fded -[UIWindow _sendTouchesForEvent:] + 567
12 UIKit 0x00810c37 -[UIApplication sendEvent:] + 447
13 UIKit 0x00815f2e _UIApplicationHandleEvent + 7576
14 GraphicsServices 0x01c91992 PurpleEventCallback + 1550
15 CoreFoundation 0x01531944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
16 CoreFoundation 0x01491cf7 __CFRunLoopDoSource1 + 215
17 CoreFoundation 0x0148ef83 __CFRunLoopRun + 979
18 CoreFoundation 0x0148e840 CFRunLoopRunSpecific + 208
19 CoreFoundation 0x0148e761 CFRunLoopRunInMode + 97
20 GraphicsServices 0x01c901c4 GSEventRunModal + 217
21 GraphicsServices 0x01c90289 GSEventRun + 115
22 UIKit 0x00819c93 UIApplicationMain + 1160
23 ARSSReader 0x00001e79 main + 121
24 ARSSReader 0x00001df5 start + 53
)
terminate called throwing an exception(gdb)
但是,如果我添加了项目,重新启动了应用程序,然后将其删除,则效果非常好。
我添加了商品,重新启动了应用,删除了商品,并尝试添加新商品:
2011-09-25 20:19:19.212 ARSSReader[36461:11303] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
*** Call stack at first throw:
(
0 CoreFoundation 0x015505a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x016a4313 objc_exception_throw + 44
2 CoreFoundation 0x01508ef8 +[NSException raise:format:arguments:] + 136
3 CoreFoundation 0x01508e6a +[NSException raise:format:] + 58
4 CoreFoundation 0x01547cf1 -[__NSCFArray insertObject:atIndex:] + 209
5 CoreFoundation 0x01544c14 -[__NSCFArray addObject:] + 68
6 ARSSReader 0x00004b35 -[DetailsViewController addToFavorites] + 149
7 UIKit 0x0080b4fd -[UIApplication sendAction:to:from:forEvent:] + 119
8 UIKit 0x00a1dcc3 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 156
9 UIKit 0x0080b4fd -[UIApplication sendAction:to:from:forEvent:] + 119
10 UIKit 0x0089b799 -[UIControl sendAction:to:forEvent:] + 67
11 UIKit 0x0089dc2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
12 UIKit 0x0089c7d8 -[UIControl touchesEnded:withEvent:] + 458
13 UIKit 0x0082fded -[UIWindow _sendTouchesForEvent:] + 567
14 UIKit 0x00810c37 -[UIApplication sendEvent:] + 447
15 UIKit 0x00815f2e _UIApplicationHandleEvent + 7576
16 GraphicsServices 0x01c91992 PurpleEventCallback + 1550
17 CoreFoundation 0x01531944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
18 CoreFoundation 0x01491cf7 __CFRunLoopDoSource1 + 215
19 CoreFoundation 0x0148ef83 __CFRunLoopRun + 979
20 CoreFoundation 0x0148e840 CFRunLoopRunSpecific + 208
21 CoreFoundation 0x0148e761 CFRunLoopRunInMode + 97
22 GraphicsServices 0x01c901c4 GSEventRunModal + 217
23 GraphicsServices 0x01c90289 GSEventRun + 115
24 UIKit 0x00819c93 UIApplicationMain + 1160
25 ARSSReader 0x00001e79 main + 121
26 ARSSReader 0x00001df5 start + 53
)
terminate called throwing an exception(gdb)
答案 0 :(得分:8)
在addToFavorites
NSMutableArray* favoritedAlready = [[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"];
将返回一个NSArray(保存一个可变版本没有区别),而不是NSMutableArray
您需要创建一个可变版本:
NSMutableArray* favoritedAlready = [[[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"] mutableCopy];
显然,您不能将项目添加到不可变数组中。同样只是将返回值强制转换为NSMutableArray是错误的,它可能有用,也可能没有,但这是无关紧要的。
答案 1 :(得分:3)
问题是NSUserDefaults只返回不可变数组,即使你放入一个可变数组:
特别注意事项: 返回的数组及其内容是不可变的,即使您最初设置的值是可变的。
因此,当您从NSUserDefaults获取数组时,您必须使用可变复制方法或使用返回的NSArray创建新的NSMutableArray来转换它。
<小时/> 您可能希望将更改合并到NSUserDefaults的更少方法调用 - 可能是批量生成,也许是在某些时间间隔。让本地数组跟踪更改,然后写出更改,而不是首先从 NSUserDefaults获取数组。这将节省一次磁盘行程,并使您的代码更高效。