【发布时间】:2014-12-18 17:07:08
【问题描述】:
我原以为这是一个身份,但它现在似乎对我不起作用。
看我的 lldb 提示:
po [self class] ==> MyCustomClass
po [MyCustomClass class] ==> MyCustomClass
po [self class] == [MyCustomClass class] ==> 是的
p [self isKindOfClass:[MyCustomClass class]] ==> '\0'(即假)。
isKindOfClass 的定义:“返回一个布尔值,指示接收者是给定类的实例还是从该类继承的任何类的实例。”
什么样的废话(我的错或其他)可能导致这种行为?
关心的人的背景:不幸的是,我正在使用第 3 方 API,该 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];
});
}
这个 sn-p 对我来说编译得很好,但是在运行时我得到一个错误:
NSInvalidArgumentException', reason: '+[MyCustomClass makeInterfaceChange]: unrecognized selector sent to class 0xf3fad8
换句话说,data 似乎实际上并不指向 MyCustomClass 的实例。是的,makeInterfaceChange 是为 MyCustomClass 定义的,否则它不会编译。正如我之前提到的,在此函数的断点处从 lldb 调用 po [data class] 会得到 MyCustomClass。
有什么想法吗?
等等,可以吗?:这部分代码中的关键 (__bridge) 转换不是语法高亮,尽管 它在我的项目中的其他任何地方。问题?或者只是 XCode 像往常一样对语法高亮很挑剔?是否有任何愚蠢的错误可能导致 __bridge 无法工作?
【问题讨论】:
-
完全正确,您应该将
isKindOfClass:的返回值转换为BOOL:p (BOOL)[self isKindOfClass:[MyCustomClass class]]但这不会改变答案,只是您得到的表示。并且不要使用po——这是针对对象的。 -
Garrett - 抱歉我之前的回答不正确;感谢您的澄清。我猜你正在使用的库重新实现
isKindOfClass并破坏它。 -
isMemberOfClass:给你什么?什么是图书馆?为什么它使用void *而不是id? -
或者这门课以某种方式让我无法理解。
-
错误消息中的
+表示myViewController是类对象,而不是实例。这几乎解释了一切。
标签: ios objective-c cocoa-touch inheritance lldb