objective-c 使用 RespondsToSelector 时抑制“'...' 已弃用”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1902021/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Suppressing "'…' is deprecated" when using respondsToSelector
提问by s4y
I'm supporting 10.4+ by picking the most-current API at runtime:
我通过在运行时选择最新的 API 来支持 10.4+:
if ([fileManager respondsToSelector:@selector(removeItemAtPath:error:)])
[fileManager removeItemAtPath:downloadDir error:NULL];
else
[fileManager removeFileAtPath:downloadDir handler:nil];
In this case, 10.5 and up will use removeItemAtPath:error:and 10.4 will use removeFileAtPath:handler:. Great, but I still get compiler warnings for the old methods:
在这种情况下,10.5 及更高版本将使用removeItemAtPath:error:,10.4 将使用removeFileAtPath:handler:. 很好,但我仍然收到旧方法的编译器警告:
warning: 'removeFileAtPath:handler:' is deprecated [-Wdeprecated-declarations]
Is there a syntax of if([… respondsToSelector:@selector(…)]){ … } else { … }that hints the compiler (Clang) to not warn on that line?
是否有语法if([… respondsToSelector:@selector(…)]){ … } else { … }提示编译器(Clang)不要在该行发出警告?
If not, is there a way to tag that line to be ignored for -Wdeprecated-declarations?
如果没有,有没有办法标记要忽略的那一行-Wdeprecated-declarations?
After seeing some of the answers, let me clarify that confusing the compiler into not knowing what I'm doing is not a valid solution.
在看到一些答案之后,让我澄清一下,让编译器混淆成不知道我在做什么并不是一个有效的解决方案。
回答by s4y
I found an examplein the Clang Compiler User's Manual that lets me ignore the warning:
我在 Clang Compiler User's Manual 中找到了一个示例,可以让我忽略警告:
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
}
回答by kperryua
You could declare a separate file that is designated for calling deprecated methods and set the per-file compiler flags in Xcode to ignore -Wdeprecated-declarations. You can then define a dummy function in that file to call the deprecated methods, and thereby avoid the warnings in your real source files.
您可以声明一个单独的文件,指定用于调用已弃用的方法,并将 Xcode 中的每个文件编译器标志设置为 ignore -Wdeprecated-declarations。然后,您可以在该文件中定义一个虚拟函数来调用已弃用的方法,从而避免在您的真实源文件中出现警告。
回答by Martin Gordon
I'm not sure if clang is smart enough to catch this, but if it's not, you could try using performSelector:withObject:withObject:or building and invoking an NSInvocation object.
我不确定 clang 是否足够聪明来捕捉到这个,但如果不是,你可以尝试使用performSelector:withObject:withObject:或构建和调用 NSInvocation 对象。
回答by Matt Ball
You could just cast fileManagerto an id— idsare able to refer to any Objective-C object, so the compiler isn't supposed to check methods which are called on one:
您可以只强制fileManager转换为id-ids能够引用任何 Objective-C 对象,因此编译器不应该检查在一个对象上调用的方法:
[(id)fileManager removeItemAtPath:downloadDir error:NULL];
shouldn'traise any warnings or errors.
不应引发任何警告或错误。
Of course, this raises other problems — namely, you lose allcompile-time checking for methods called on the id. So if you misspell you method name, etc, it wont be caught until that line of code is executed.
当然,这引发了其他问题-即,你失去所有的编译时检查的呼吁方法id。因此,如果您拼错了方法名称等,则在执行该行代码之前不会被捕获。
回答by Quinn Taylor
If you consider any form of "confusing" the compiler to be an invalid solution, you're probably going to have to live with the warning. (In my book, if you asking how to get rid of a warning, it's unwise to look a gift horse in the mouth and say something is invalid just because it doesn't look like you'd expect.)
如果您认为任何形式的“混淆”编译器是无效的解决方案,您可能不得不忍受警告。(在我的书中,如果你问如何摆脱警告,只是因为它看起来不像你期望的那样,就嘴上看着一匹礼物马并说某事无效是不明智的。)
The answers that work at runtime involve masking the operation that's happening with dynamic dispatch so the compiler doesn't complain about the deprecated call. If you don't like that approach, you can turn off "Warn About Deprecated Functions" in your Xcode project or target settings, but that's generally a bad idea. You want to know about deprecated APIs, but in this case you want to use it without warning. There are easy and hard ways to do this, and odds are you'd consider all of them "invalid" in some form, but that doesn't prevent them from being effective, even correct. ;-)
在运行时工作的答案涉及屏蔽动态分派发生的操作,因此编译器不会抱怨已弃用的调用。如果您不喜欢这种方法,您可以在您的 Xcode 项目或目标设置中关闭“关于已弃用的函数的警告”,但这通常是一个坏主意。您想了解已弃用的 API,但在这种情况下,您希望在没有警告的情况下使用它。有简单和困难的方法可以做到这一点,而且您可能会认为所有这些方法都以某种形式“无效”,但这并不妨碍它们有效,甚至是正确的。;-)
One possible way to avoid the warnings yet still select at runtime is to use objc_msgSend()directly:
避免警告但仍然在运行时选择的一种可能方法是objc_msgSend()直接使用:
objc_msgSend(fileManager, @selector(removeFileAtPath:error:), downloadDir, nil];
This is what the Objective-C runtime does under the covers anyway, and should accomplish the result you want with a minimum of fuss. You can even leave the original line commented above it for clarity. I know the documentation says, "The compiler generates calls to the messaging function. You should never call it directly in the code you write."You alone have to decide when it's okay to bend the rules.
无论如何,这就是 Objective-C 运行时在幕后所做的事情,并且应该以最少的麻烦完成您想要的结果。为了清楚起见,您甚至可以将原始行注释在其上方。我知道文档说,“编译器生成对消息传递函数的调用。你永远不应该在你编写的代码中直接调用它。” 您必须独自决定何时可以违反规则。

