我原以为这是身份,但它现在似乎并不适合我。
看到我的lldb提示:
po [self class]
==> MyCustomClass
po [MyCustomClass class]
==> MyCustomClass
po [self class] == [MyCustomClass class]
==>真
p [self isKindOfClass:[MyCustomClass class]]
==> ' \ 0' (即假)。
isKindOfClass的定义:"返回一个布尔值,指示接收者是给定类的实例还是从该类继承的任何类的实例。"
什么样的废话(我的错误或其他)会导致这种行为?
对于那些关心的人的背景:我很遗憾地使用第三方API,它需要我将对象作为void指针传入,然后将其强制转换为正确的类型。尽管所有内容都编译得很好,但在运行时我被告知该对象并不能识别我试图发送给它的选择器。这意味着(我认为?)它实际上并不是我将其投射到的类的实例。在尝试测试时,我遇到了[NSObject isKindOfClass]
这个问题。到底是怎么回事?
在iOS 8.1 iPad上运行,在XCode 6.1.1中构建。
这是最后一次测试的截图:
进展编辑:我终于设法使用this post在这个库运行的线程中得到一个断点,并且看到一些更疯狂的东西。
给定(void*)data
,我得到:
po [data class]
==> MyCustomClass
po [data isKindOfClass:[MyCustomClass class]]
==> nil
(再次,这只是假的)
显然我在这里真的打破了一些东西。是否存在可能导致类似问题的已知问题?
编辑 SSCCE-ish示例:您从一个裸C函数开始,该函数作为回调函数传递给后台库:
void libraryCallbackFunction(eventname, stuff, (void*)data)
当事件发生时,库会调用此函数(来自新线程),并使用此函数来处理事件。 data
应该是指向要从此事件处理函数调用的任何旧类的指针。在此函数中,您可以将数据转换为所需的任何类。然后,您可以将消息发送到主线程上的数据实例。我们称之为视图控制器:
void libraryCallbackFunction((void*)data) {
MyCustomClass *myViewController = (__bridge MyCustomClass*)data;
/* stuff stuff stuff */
dispatch_async(dispatch_get_main_queue(), ^{
[myViewController makeInterfaceChange];
});
}
这段代码对我来说很好,但在运行时我收到错误:
NSInvalidArgumentException', reason: '+[MyCustomClass makeInterfaceChange]: unrecognized selector sent to class 0xf3fad8
换句话说,似乎data
实际上并未指向MyCustomClass的实例。是的,makeInterfaceChange是为MyCustomClass定义的,否则它不会编译。正如我之前提到的,在此函数的断点处从lldb调用po [data class]
会给MyCustomClass
。
有什么想法吗?
等待,可能是吗?:代码的这一部分中的关键(__bridge)演员不是语法高亮,即使它在我的项目中的其他地方。问题?或者只是像往常一样,XCode在语法高亮方面很挑剔?是否有任何可能导致__bridge不起作用的骨头错误?
答案 0 :(得分:2)
您正在注册要传递给回调的类对象,而不是实例。这由异常消息中的+
表示。
isKindOfClass:
的奇怪之处正在发生,因为[someClassObject class]
返回自身,而不是其类(这将是一个元类对象)。但是,类对象不是它自己的类(不是它所代表的类的成员); they have their own (opaque) hierarchy
[[NSString class] isKindOfClass:[NSString class]]
例如,产生与代码相同的结果:NO
。