isKindOfClass莫名其妙的身份问题

时间:2014-12-18 17:07:08

标签: ios objective-c cocoa-touch inheritance lldb

我原以为这是身份,但它现在似乎并不适合我。

看到我的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中构建。

这是最后一次测试的截图:

lldb screenshot


进展编辑:我终于设法使用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不起作用的骨头错误?

1 个答案:

答案 0 :(得分:2)

您正在注册要传递给回调的类对象,而不是实例。这由异常消息中的+表示。

isKindOfClass:的奇怪之处正在发生,因为[someClassObject class]返回自身,而不是类(这将是一个元类对象)。但是,类对象不是它自己的类(不是它所代表的类的成员); they have their own (opaque) hierarchy

[[NSString class] isKindOfClass:[NSString class]]
例如,产生与代码相同的结果:NO