【问题标题】:NSMutableArray removeAllObjects results in a crashNSMutableArray removeAllObjects 导致崩溃
【发布时间】:2013-01-27 21:20:28
【问题描述】:

我的ViewController 中有一个NSMutableArray,它是我的UITableView 的数据源,定义如下:

NSMutableArray *messageArray;

我有一个重新加载tableView数据的方法,在此之前,我想清除现有的表格数据。

如果我使用以下代码:

  [messageArray removeAllObjects];    
  [self.tableView reloadData];

我得到以下异常:

2013-02-12 14:20:30.378 appname[20998:907] * 终止应用程序由于 未捕获的异常“NSInternalInconsistencyException”,原因: '-[__NSCFArray removeObjectAtIndex:]: 变异方法发送到 不可变对象' * 第一次抛出调用栈:(0x3939e3e7 0x35dd6963 0x3939e307 0x393200e7 0x392eb5e5 0x7cda3 0x3a236047 0x3a2360d1 0x3a236047 0x3a235ffb 0x3a235fd5 0x3a23588b 0x3a235d79 0x3a15e5c9 0x3a14b8b1 0x3a14b1bf 0x336305f7 0x33630227 0x393733e7 0x3937338b 0x3937220f 0x392e523d 0x392e50c9 0x3362f33b 0x3a19f291 0x79c11 0x39be4b20) libc++abi.dylib:终止调用抛出异常

但如果我使用下面的代码,它就可以工作。

  NSMutableArray *emptyArray = [NSMutableArray new];
  messageArray = emptyArray;    
  [self.tableView reloadData];

为什么我收到removeAllObjects 的错误? 这可能是罪魁祸首吗?

    NSMutableDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
    messageArray = responseDictionary[@"data"];

【问题讨论】:

标签: ios exception ios6 nsmutablearray


【解决方案1】:

看起来你的“NSMutableArray”实际上是一个 NSArray 转换为 NSMutableArray。

在您的代码中搜索类似的内容:

messageArray = (NSMutableArray *)[obj methodReturningNSArray];

removeAllObjects 仅适用于真正的 NSMutableArray,因为错误“将方法发送到不可变对象”状态。

【讨论】:

  • 我没有类似的东西,但我确实认为它以某种方式被强制转换为 NSArray
  • 默认情况下,JSON 创建的是 NSArray 而不是 NSMutableArrays,所以你的猜测是正确的。如 tkanzakic 所示,在数组上使用 mutableCopy 是一种解决方案,即 messageArray = [responseDictionary[@"data"] mutableCopy];
【解决方案2】:

数据重新加载返回的messageArray 不是NSMutableArray,而是NSArray。如果在重新加载后放置调试器停止,您可以验证这一点。设置messageArray时使用.mutableCopy

【讨论】:

    【解决方案3】:

    你必须改变这一行:

    messageArray = responseDictionary[@"data"];
    

    到:

    messageArray = [responseDictionary[@"data"] mutableCopy];
    

    默认情况下,您从字典中获取的对象是非可变对象

    【讨论】:

    • 不,您从字典中获取的对象是您之前放入其中的对象。如果反序列化取决于反序列化代码。 NSPropertyListSerialization 例如支持两者。
    • 是的,你是对的,我的意思是来自NSJSONSerialization,除非你指定你对可变副本感兴趣
    • 啊,我明白了。对不起,听起来很时髦。
    【解决方案4】:

    如何找到出错的地方:

    1. 检查您是否@synthesize 名为messageArray 的属性。如果此属性是 NSArray 类型或使用 copy 修饰符声明的,则合成的 setter 是罪魁祸首。
    2. 如果不是,请重新声明 ivar NSMutableArray *const messageArray。现在编译器将向您显示每个分配。检查 NSArray 分配。之后不要忘记恢复声明。
    3. 完成后,将 ivar 重命名为 _messageArray,以便将来更快地找到直接访问。

    【讨论】:

      【解决方案5】:

      您在某处将NSMutableArray 设置为NSArray 的实例,而不是NSMutableArray,或者您将NSMutableArray 声明为NSArray vs. NSMutableArray 类型的属性。

      Cocoa 文档使用单词immutable指代只读初始化后无法更改对象

      此外,您应该遵循Cocoa / Objective-C 命名约定。即类名以大写开头;变量采用 myArray 的形式(或更具描述性的形式,最好是)。

      您可以在copyWithZone referenceNSMutableCopying protocol reference 中找到更多详细信息。

      【讨论】:

        【解决方案6】:

        这可能是罪魁祸首吗?

        NSMutableDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:nil];
        messageArray = responseDictionary[@"data"];
        

        是的,您想使用可变容器的选项:

        NSMutableDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options: NSJSONReadingMutableContainers error:NULL];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-11
          相关资源
          最近更新 更多