使用respondsToSelector时,禁止“'...'被弃用”

时间:2009-12-14 16:44:45

标签: objective-c cocoa xcode clang

我通过在运行时选择最新的API来支持10.4+:

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)])
    [fileManager removeItemAtPath:downloadDir error:NULL];
else
    [fileManager removeFileAtPath:downloadDir handler:nil];

在这种情况下,10.5及以上将使用removeItemAtPath:error:,10.4将使用removeFileAtPath:handler:。很好,但我仍然得到旧方法的编译器警告:

warning: 'removeFileAtPath:handler:' is deprecated [-Wdeprecated-declarations]

是否有if([… respondsToSelector:@selector(…)]){ … } else { … }的语法提示编译器(Clang)不在该行上发出警告?

如果没有,有没有办法在-Wdeprecated-declarations

标记该行被忽略

在看到一些答案之后,让我澄清一下,混淆编译器而不知道我在做什么并不是一个有效的解决方案。

5 个答案:

答案 0 :(得分:115)

我在Clang编译器用户手册中找到了an example,让我忽略了警告:

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)]) {
    [fileManager removeItemAtPath:downloadDir error:NULL];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    [fileManager removeFileAtPath:downloadDir handler:nil];
#pragma clang diagnostic pop
}

答案 1 :(得分:8)

您可以声明一个指定用于调用弃用方法的单独文件,并在Xcode中设置每个文件编译器标志以忽略-Wdeprecated-declarations。然后,您可以在该文件中定义虚拟函数以调用已弃用的方法,从而避免实际源文件中的警告。

答案 2 :(得分:6)

我不确定clang是否足够智能来捕获它,但如果不是,则可以尝试使用performSelector:withObject:withObject:或构建并调用NSInvocation对象。

答案 3 :(得分:5)

你可以将fileManager转换为id - ids能够引用任何Objective-C对象,因此编译器不应该检查被调用的方法之一:

[(id)fileManager removeItemAtPath:downloadDir error:NULL];

不应提出任何警告或错误。

当然,这会引发其他问题 - 即,您在id上调用的方法会丢失所有编译时检查。因此,如果您拼错了方法名称等,则在执行该行代码之前不会被捕获。

答案 4 :(得分:3)

如果您认为任何形式的“混淆”编译器都是无效的解决方案,您可能不得不接受警告。 (在我的书中,如果你问如何摆脱警告,在口中看到一匹礼物马是不明智的,只是因为看起来不像你期望的那样,说某些东西是无效的。)

在运行时工作的答案涉及屏蔽动态调度所发生的操作,因此编译器不会抱怨已弃用的调用。如果您不喜欢这种方法,可以在Xcode项目或目标设置中关闭“警告关于不推荐使用的功能”,但这通常是个坏主意。您想了解已弃用的API,但在这种情况下,您希望在不发出警告的情况下使用它。有很简单的方法可以做到这一点,你可能会认为它们在某种形式下都是“无效的”,但这并不妨碍它们有效,甚至是正确的。 ; - )

避免警告但仍然在运行时选择的一种可能方法是直接使用objc_msgSend()

objc_msgSend(fileManager, @selector(removeFileAtPath:error:), downloadDir, nil];

This is what the Objective-C runtime does under the covers anyway,并且应该以最小的麻烦完成你想要的结果。为清晰起见,您甚至可以将原始行留在其上方。我知道文档说,“编译器会生成对消息传递函数的调用。你永远不应该直接在你编写的代码中调用它。”你必须决定何时可以修改规则。< / p>