I want to make a "Favorites" in my RSS reader. My RSS parser is parsing a RSS feed to NSMutableArray, and then object "item" is created from part of my rss (selected post). My code:
//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];
}
It worked perfectly initially, but when I added and removed items, it started crashing. Crash logs: I added object to Favorites and removed it:
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)
But, if I added item, restarted app and then removed it, it worked perfectly.
I added item, restarted app, removed item, and tried to add new item:
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)
In addToFavorites
NSMutableArray* favoritedAlready = [[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"];
will return an NSArray (it makes no difference it you save a mutable version), not an NSMutableArray
You need to create a mutable version:
NSMutableArray* favoritedAlready = [[[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"] mutableCopy];
You can obviously not add items to a non-mutable array. Also just casting the return value to a NSMutableArray is wrong, it may work or it may not but that is irrelevant.
The issue is that NSUserDefaults only returns immutable arrays, even if you put in a mutable array:
Special Considerations : The returned array and its contents are immutable, even if the values you originally set were mutable.
Therefore, when you fetch your array from NSUserDefaults, you'll have to convert it by using the mutable copy method, or by creating a new NSMutableArray using the returned NSArray.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.