user3405229 user3405229 - 1 month ago 16
Objective-C Question

iOS error "[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object"

The Error:




Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'



The Code:



.h


@property (nonatomic, strong) NSMutableArray *history;


.m


- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString *de = [[self.history objectAtIndex:indexPath.row] objectForKey:@"des"];
NSString *dest = [de stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *jsonURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://example.com/rm_history.php?user_id=%@&destinations=%@",self.uID,dest]];
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL];
[self.history removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]
withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
NSLog(@"create");
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
[self.tableView reloadData];
}


After setting a breakpoint to catch the error it stops at this line :

[self.history removeObjectAtIndex:indexPath.row];


Any idea on what's causing the problem ?

Answer

The fact that you declare history a NSMutableArray does not mean that only NSMutableArray can be assigned to it. It is possible to assign an immutable NSArray to the history if you are not careful. For example, this is what will happen if you serialize NSMutableArray, say, to JSON, and then deserialize it back to NSMutableArray: you would get an NSArray instead.

To avoid this issue, make sure that you always assign history either a NSMutableArray that you create, or a result of calling a mutableCopy on an NSArray that you receive from other parts of your code:

self.history = [[dataDictionary objectForKey:@"ds_history"] mutableCopy];
Comments