iOS错误"[__NSCFArray removeObjectAtIndex:]:发送给不可变对象的可变方法"。

5

错误:

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

在设置了断点以捕获错误后,它会停在这一行:

[self.history removeObjectAtIndex:indexPath.row];

有什么想法导致这个问题的出现吗?

1
你要给 history 属性分配什么值?它是在哪里创建的? - David Rönnqvist
self.history 可能被声明为不可变的,因此应该使用 NSArray 而不是 NSMutableArray - Volker
2
@Volker 不是的,你可以在问题中看到它被声明为可变数组。但这并不意味着 OP 给它分配了一个可变数组。 - David Rönnqvist
在viewDidLoad中声明:self.history = [dataDictionary objectForKey:@"ds_history"];,其中dataDictionary是数据字典。 - user3405229
1
错误信息告诉您,在某个地方将 NSArray 赋给了 self.history,而不是 NSMutableArray。您需要查找每个设置 self.history 的代码位置来确定问题所在。请注意,如果 dataDictionary 为键 ds_history 分配了一个数组,则由您决定是确保它实际上是一个 NSMutableArray 还是调用 self.history = [[dataDictionary objectForKey:@"ds_history"] mutableCopy] - Robotic Cat
4个回答

27

声明historyNSMutableArray并不意味着只有NSMutableArray可以分配给它。如果您不小心的话,可能会将不可变的NSArray分配给history。例如,如果您将NSMutableArray序列化为JSON,然后将其反序列化回NSMutableArray,则会得到一个NSArray

要避免此问题,请确保始终将history分配给您创建的NSMutableArray,或者调用从代码其他部分接收的NSArray上的mutableCopy的结果:

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

我已经尝试过了,但它并没有起作用,而且还给我同样的错误。 - user3405229
我已经重新实现了它,现在它运行得很好,非常感谢! - user3405229

0
您遇到此问题是因为NSUserDefaults始终返回不可变对象。
请在从NSUserDefaults检索可变对象时参考以下代码。
NSMutableArray *storeArray = [[defaultDefects objectForKey:@"defaultStoreDefects"] mutableCopy];

0

*NSUserDefaults总是返回一个不可变对象*

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

NSMutableArray *history;

--> 用于保存或存储

[userDefaults setObject:histrory forKey:@"des"];
[userDefaults synchronize];

-->用于检索

history = [[userDefaults objectForKey:@"des"] mutableCopy];

-1

我认为当self.history被赋值时,它被转换为NSArray

请尝试下面的代码:

self.history = [NSMutableArray arrayWithArray:[dataDictionary objectForKey:@"ds_history"]];

你可以随意转换指针类型,但这并不会改变对象的类型。 - Hot Licks
Hot Licks - 我应该说[dataDictionary objectForKey:@"ds_history"]可能是NSArray。我没有说[dataDictionary objectForKey:@"ds_history"]被强制转换为NSArray。 - HMHero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接