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

Posted

技术标签:

【中文标题】如何了解哪个无法识别的选择器发送到实例【英文标题】:How to understand which unrecognized selector sent to instance 【发布时间】:2014-03-26 10:44:09 【问题描述】:

我如何从这个错误消息中找出这是哪个选择器?

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

如何让 xcode 给我正常的错误消息,告诉我问题出在哪里?

【问题讨论】:

它在错误消息中说明发送了什么消息,以及发送到什么样的对象。只需仔细阅读信息并动动您的大脑。仔细想想,这就是你问题的准确和正确答案。 错误消息说无法识别的选择器已发送到 NSArray,当我放置断点异常时,无法识别的选择器来自通过 xib 连接的 UILabel 并落在此行 [_label setText:name] , _label 不是零,“名称”也不是,所以问题是什么,为什么它会下降???当错误在标签 setText 行中时,为什么它说错误在 NSArray 中? lengthNSString 的一个方法。所以我猜name 实际上是NSArray 而不是NSString,因为它应该是。当您使用 setText: 分配数组时,标签会调用特定于字符串的方法。 你有内存问题,一些悬空指针或提前释放的对象。 【参考方案1】:

这是一条正常的错误消息。系统不能告诉你更多。

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

这是我们从异常消息中了解到的:

    无法识别的选择器是length。具有此方法的最常见类是NSString。 接收此方法的对象是NSArray 触发异常断点后,在调试器中输入po 0x178059b30 以检查数组。该数组的内容可以提示您找出问题最初是如何引起的。 从代码中的调试器位置,您可以看到触发错误的原因。

您说您的代码在[_label setText:name] 失败。

这个方法需要一个 NSString,在赋值过程中会调用几个 NSString 特定的方法,length 是这些方法之一。这证实了我们的猜测之一。

有两种可能:

    name 实际上是一个 NSArray,因为您编写的代码分配了错误的对象。如果您不检查从字典或数组中获得的结果,通常会发生这种情况。 你有一个内存问题,name 被提前释放,数组现在是 NSString 应该在的位置。

要排除第二个选项,通常运行分析器就足够了。它将指出大多数内存问题。

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

如果你使用一个属性,你可以使用这样的东西来找出你在哪里分配了错误的对象:

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

当分配的对象不是 NSString 实例时将触发断点,您可以检查调用堆栈以查看您在哪里做错了。 确保在完成调试后删除该代码。您不得使用此类检查来防止代码中的错误。

【讨论】:

以上是关于如何了解哪个无法识别的选择器发送到实例的主要内容,如果未能解决你的问题,请参考以下文章

NSInvalidArgumentException,使用 performSegueWithIdentifier 时发送到实例的无法识别的选择器

快速代码崩溃:“发送到实例的无法识别的选择器”

ios 7无法识别的选择器发送到实例

Swift 3:将无法识别的选择器发送到手势识别器实例

无法识别的选择器发送到实例,UISlider swfit3

如何解决“发送到实例的无法识别的选择器”?