繁体   English   中英

在什么条件下,instancesRespondToSelector:返回true,但是performSelector:抛出异常

[英]Under what conditions might instancesRespondToSelector: return true, but performSelector: throw an exception

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

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:方法时, -[__NSCFString JSONValue]: unrecognized selector sent to instance异常的-[__NSCFString JSONValue]: unrecognized selector sent to instance被抛出。 这是在我编写的库中分发的代码,但我自己无法重现或调试它。 相反,第三方报告此问题。 在什么条件下, instancesRespondToSelector:实际上使用performSelector:调用方法performSelector:抛出异常?

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

@implementation NSString (OurHappyCategory)

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

@end

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

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

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 /运行时差异?

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

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

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

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

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

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

确保没有人在调整功能

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM