为什么在ARC下,“no known method for selector x”是一个严格的错误?

4
也许将 MyClass 类型的某个方法调用 MyClass 不理解的内容视为错误而不是警告会更有用,因为这可能是一个错误,或者将来会导致错误...
然而,为什么这个错误只与 ARC 有关呢?ARC 根据 Cocoa 内存管理约定决定何时需要保留/释放/自动释放,这表明知道选择器的名称就足够了。因此,将 SEL 变量传递给 performSelector: 存在问题是有道理的,因为在编译时无法确定选择器是否是 init/copy/new 方法。但为什么在类接口中看到这一点或不看到这一点会有任何区别呢?
我是否对 ARC 的工作方式有所遗漏,还是 clang 警告有些不一致?
2个回答

9
ARC根据Cocoa内存管理约定决定需要保留/释放/自动释放的内容,这表明了知道选择器名称就足够了。这只是ARC确定内存管理的一种方式。ARC还可以通过属性确定内存管理。例如,您可以声明任何typedef使用__attribute__((NSObject))以使其可保留(永远不要这样做,但是它是合法的)。您还可以使用其他属性,如__attribute((ns_returns_retained))和一些其他属性来覆盖命名约定(如果您无法更改命名,则可能会合理地执行此操作;但最好更改命名)。现在,想象一种情况,您在某些文件中未包含声明这些属性的头文件,而在其他文件中却包含了。现在,某些编译单元(.m文件)对其进行的内存管理方式与其他编译单元不同。这比没有ARC的情况要糟糕得多,由于某些ARC代码会执行一种操作,而其他ARC代码将执行不同的操作,因此导致的错误会令人震惊。所以,不要这样做。(当然,在Objective-C中不应忽略警告,但这是一种特别严重的情况。)

你介意删除关于如何覆盖命名约定的内容吗? ;) - Chris Devereux
只要它从http://clang.llvm.org/docs/AutomaticReferenceCounting.html中删除,就会尽快更新。但是克里斯是正确的,这通常不是一个好的解决方案。这比在ARC下泄漏和崩溃要好得多。但是正确的解决方案是修复您的命名以符合ObjC的命名约定。 - Rob Napier

1

这是一种预防措施,我想。顺便说一下,在更大的系统中它并不是万无一失的,因为选择器不需要匹配,匹配全部基于翻译,所以如果你没有编写程序引入类型安全性,它仍然可能会出问题。但总比什么都不做好!

编译器想要知道参数和返回类型,潜在的注释和输出参数。ObjC有默认值可以回退,但随着编译器为您完成的工作越来越多,它也是多种类型错误的一个好源头。

有很多理由应该引入类型安全并提高警告级别。使用ARC,还有更多的原因。无论是否真正必要,这对于objc编译器来说都是一个好的方向(在我看来)。你可能认为C99在这方面比ObjC 2.0更安全 ;)

如果真的有代码生成的限制,我想听听它。


当然。但是在这种情况下,ARC有什么特别之处?如果意图是提高类型安全性,为什么只在ARC下将其作为错误,并为错误消息添加“ARC”前缀? - Chris Devereux
@Chris 啊,但是 performSelector: 可以 使用运行时的帮助来实现——它不是必须是一个错误。在这里也是一样的。未声明选择器的参数类型规则已经被定义了。 - justin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接