使用respondsToSelector时,禁止"'...'被弃用"

s4y*_*s4y 56 xcode cocoa objective-c clang

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

if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)])
    [fileManager removeItemAtPath:downloadDir error:NULL];
else
    [fileManager removeFileAtPath:downloadDir handler:nil];
Run Code Online (Sandbox Code Playgroud)

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

warning: 'removeFileAtPath:handler:' is deprecated [-Wdeprecated-declarations]
Run Code Online (Sandbox Code Playgroud)

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

如果没有,有没有办法标记该行被忽略-Wdeprecated-declarations


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

s4y*_*s4y 117

我在Clang编译器用户手册中找到了一个示例,它让我忽略了警告:

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
}
Run Code Online (Sandbox Code Playgroud)


kpe*_*yua 8

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


Mar*_*don 6

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

  • performSelector:和kin是在运行时调用Objective-C方法的正确解决方案,当你不确定它们是否存在时. (2认同)

Mat*_*all 5

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

[(id)fileManager removeItemAtPath:downloadDir error:NULL];
Run Code Online (Sandbox Code Playgroud)

不应该提出任何警告或错误.

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