如何理解发送到实例的哪个无法识别的选择器

时间:2014-03-26 10:44:09

标签: selector nsexception

如何根据此错误消息确定哪个选择器?

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM length]: unrecognized selector sent to instance 0x178059b30'

如何让xcode给我正常的错误信息,那些会告诉我问题究竟在哪里?

1 个答案:

答案 0 :(得分:2)

这是正常的错误消息。系统无法告诉您更多信息。

但是在调试器的帮助下(启用异常断点),以及对Objective-C的良好理解,您应该能够诊断问题。

以下是我们从异常消息中得知的内容:

  1. 无法识别的选择器为length。具有此方法的最常见类是NSString
  2. 收到此方法的对象是NSArray
  3. 触发异常断点后,在调试器中键入po 0x178059b30以检查阵列。这个数组内容可以为您提供一些提示,以确定问题最初是如何引起的。
  4. 从代码中的调试器位置,您可以看到触发错误的原因。
  5. 您说您的代码在[_label setText:name]失败了。

    此方法需要NSString,在赋值期间会调用几个特定于NSString的方法,length是这些方法之一。这证实了我们猜测的一点。

    有两种可能性:

    1. name实际上是一个NSArray,因为您编写的代码分配了错误的对象。如果您不检查从字典或数组中获得的结果,通常会发生这种情况。
    2. 您遇到了内存问题,并且name过早被释放,现在数组就是NSString所在的位置。
    3. 要排除第二个选项,分析器的运行通常就足够了。它将指出大多数内存问题。

      另一种决定使用po 0x178059b30输出的方式更有可能的方法。如果数组包含与name的预期值相关的对象(例如,它实际上包含name),则很有可能您分配了错误的对象。在这种情况下,查看您设置名称的位置,并对其进行检查。

      如果您使用属性,则可以使用类似的内容来确定分配错误对象的位置:

      - (void)setName:(NSString *)name
           _name = [name copy];
           if (![name isKindOfClass:[NSString class]]) {
               NSAssert(NO, @"Wrong class %@", name);     
           }
      }
      

      当分配的对象不是NSString实例时,将触发断点,您可以检查调用堆栈以查看出错的位置。
      完成调试后,请务必删除该代码。您不得使用此类检查来防止代码中的错误。