【问题标题】:isKindOfClass inexplicable identity issueisKindOfClass 莫名其妙的身份问题
【发布时间】: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


【解决方案1】:

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

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

[[NSString class] isKindOfClass:[NSString class]]

例如,产生与您的代码相同的结果:NO

【讨论】:

  • 这个库是用类似startLibraryInBackground(callbackFunction, dataObject, stuff) 的函数启动的,我的愚蠢错误是在我的viewController 类的静态方法中将self 作为dataObject 参数传递。所以它得到的是类本身,而不是实例。谢谢!
  • 很高兴我能帮上忙。 (但请记住:they're not "static" methods in ObjC。:)
猜你喜欢
  • 2011-11-22
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 2012-03-12
  • 2019-02-04
  • 2013-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多