9

在 ARC 之前,我有一个“X 可能无法响应 xxx”警告,这是一个非常无害的警告,不会阻止它编译。现在,我正在尝试将我的项目转换为 ARC,并且出现“No visible @interface for X declarations the selector xxx”错误,这会阻止它编译。

我确切地知道我在做什么,以及为什么出现警告,我可以告诉你程序是正确的。以前,编译器编译它没有问题,现在不应该阻止它编译。

确实,类 X 的接口没有声明该选择器,但是 X 是一个使用(这是 Objective-C 的美丽之处之一)动态处理发送给它的任何选择器的任何forwardInvocation:消息的类,因此它的接口不可能声明所有可以在其上调用的选择器。并且选择器某处声明,而不是在 X 上。

4

3 回答 3

5

我确切地知道我在做什么,以及为什么出现警告,我可以告诉你程序是正确的。

好的 - 只需使用objc_msgSend等。如果你想直接做编译器的工作。

确实,类 X 的接口没有声明该选择器,但是 X 是一个使用 forwardInvocation 动态处理发送给它的任何选择器的任何消息的类:(这是关于 Objective-C 的美妙之处之一),所以它的接口不可能声明所有可以在其上调用的选择器。并且选择器在某处声明,而不是在 X 上。

如果声明太乏味,但在消息传递中使用似乎与您的程序对选择器的使用相矛盾……听起来像是生成代码的危险领域,需要大量人工干预。

也许您应该考虑声明一个协议,以便编译器至少可以为您正确设置消息调用 - 如果您更改或破坏某些内容,它有机会适应或通知您。

于 2012-11-21T03:42:35.227 回答
2

我不确定,但我相信在 ARC 下,编译器可以看到方法签名更重要,因为它需要知道需要什么内存管理。所以你要么需要:

  1. 通过其中一种常规方法声明您正在使用的方法(即理想情况下在真实接收器上,但如果没有其他作为类别,即使仅在 上NSObject)。
  2. 通过或其他类似方式手动执行操作NSInvocation,对内存管理负全部责任(这可能很棘手,因为您必须在 ARC 之间进行桥接)。

更新:我刚刚检查了 clang 源,确实是这样 -使用 ARC 时需要签名。这不仅仅是试图变得刻薄。:)

于 2012-11-21T03:54:53.763 回答
1

确实,类 X 的接口没有声明该选择器,但是 X 是一个使用 forwardInvocation 动态处理发送给它的任何选择器的任何消息的类:(这是关于 Objective-C 的美妙之处之一),所以它的接口不可能声明所有可以在其上调用的选择器。并且选择器在某处声明,而不是在 X 上。

如果要丢弃静态类型信息,请转换为 id。或者,如果您的对象是另一个类的代理,则可能会转换为该类。

只要该方法在标头中的某处声明(无论如何都必须如此),并且参数类型没有歧义,这应该可以解决错误。

如果您对为什么这只是启用 ARC 的问题感兴趣,请查看我提出的这个问题的答案:为什么 'no known method for selector x' 在 ARC 下是一个硬错误?

于 2013-05-21T23:32:42.837 回答