15

我的代码分布在一个库中,如下所示:

if ([[NSString class] instancesRespondToSelector: @selector(JSONValue)]) {
  NSString *jsonString = [[[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding] autorelease];
  dict = [jsonString performSelector: @selector(JSONValue)];
}

由于某种原因,调用该方法-[__NSCFString JSONValue]: unrecognized selector sent to instance时会引发异常。performSelector:这是分布在我编写的库中的代码,但我自己无法重现或调试它。相反,第三方正在报告此问题。在什么情况下instancesRespondToSelector:实际调用方法时会performSelector:抛出异常?

编辑 有一个案例可以解释为什么会发生这种情况,但这没有意义。如果开发人员要做这样的事情:

@implementation NSString (OurHappyCategory)

+ (BOOL)instancesRespondToSelector:(SEL)aSelector
{
  return YES;
}

@end

它会解释为什么代码正在执行,但这当然是一件非常糟糕的事情。有没有办法让这个问题发生有意义?

4

5 回答 5

7

NSString 基本上是一个类 cluster,并带来了各种复杂性......你实际上需要询问实例是否响应选择器。

NSString *jsonString = [[[NSString alloc] initWithData: jsonData encoding: NSUTF8StringEncoding] autorelease];
if ([jsonString respondsToSelector: @selector(JSONValue)]) {
  dict = [jsonString performSelector: @selector(JSONValue)];
}

但是您的问题可能与编译或链接扩展有关……如果在库中添加了类别,那么您将需要添加-ObjC链接器标志。

编辑:
我一直在努力重现这个问题......我无法......你有更多信息吗......例如,故障仅发生在模拟器上,或者仅发生在设备上,iOS 4 .x,GNU 链接器与 LLDB 的链接器,ABI/运行时差异?

于 2013-04-23T22:20:50.983 回答
4

该异常并非直接来自 Objective-C 运行时以响应发送实例无法识别的消息。它来自-[NSObject doesNotRecognizeSelector:],在各种方法查找和转发机制结束时调用。

但是,任何东西都可以在需要时调用-doesNotRecognizeSelector:。一个类可以通过覆盖它并使覆盖只是调用来“拒绝”继承的方法-doesNotRecognizeSelector:。正如所记录的,这将导致您看到的异常,尽管-respondsToSelector:(and +instancesRespondToSelector:) 返回YES.

我无法告诉你为什么__NSCFString在你的最终用户的情况下这样做。使用您的库的应用程序是否使用类别或方法调配来修改该类的方法?

此外,您的日志记录是否显示异常中的实际堆栈跟踪捕获?这可能是有益的。

于 2013-04-24T03:36:13.847 回答
4

我猜你没有以正确的方式导入第三方库。通常这些方法作为类别添加到 NSString,我碰巧可以看到 .h 文件但 .m 没有编译。您可以在 xcode 目标->构建阶段->编译源中检查它。或者检查你是否在 Project-->Build Settings-->Other linker flag =-all_load

于 2013-04-11T06:09:35.583 回答
0

确保没有人在调配函数

于 2013-04-23T22:37:30.020 回答
0

有一种奇怪的可能性:它performSelector本身可能以某种方式在与其余代码不同的链接加载环境中执行。不过,不完全(或什至大致)确定这是如何发生的。

于 2013-04-18T02:34:36.910 回答