否定Objective-C的@available关键字

Sta*_*ort 15 objective-c ios availability ios11 xcode9

我想只有在当前设备的iOS版本低于特定版本运行一段代码,作为指定在这里.Apple给出的代码示例如下所示:

if (@available(iOS 10.0, *)) {
  // iOS 10.0 and above
} else {
  // below 10.0
}
Run Code Online (Sandbox Code Playgroud)

但是,有些情况下,只有当前iOS版本低于特定版本时,才会运行代码.我假设以下代码将起作用:

if (!@available(iOS 10.0, *)) {
  // below 10.0
}
Run Code Online (Sandbox Code Playgroud)

但似乎这不起作用,我从Xcode收到以下警告:

@available does not guard availability here; use if (@available) instead
Run Code Online (Sandbox Code Playgroud)

是添加了我所看到的诊断的LLVM提交.

该问题有两种可能的后备:

  1. 使用if-else变体而不向if块添加任何代码(不是很优雅).
  2. 继续使用旧的方法,如-[NSProcessInfo isOperatingSystemAtLeastVersion:].

还有另一种使用@available我想要的方法吗?

Mec*_*cki 6

其想法@available是您要使用仅在某些系统上可用的API。对于其他系统,您的应用程序中缺少该功能,或者您提供了替代功能。在某些情况下,仅在下面的操作系统版本中不需要任何代码的情况下,正确的使用方式是

if (@available(iOS 10.0, *)) {
    // Happens automatically on on iOS 10 and beyond
} else {
    someOtherCode();
}
Run Code Online (Sandbox Code Playgroud)

这样做的原因是,编译器有时不得不对受其保护的代码执行一些额外的处理@available,因此需要在这种情况下清楚地识别。所以实际上它明确地搜索

if (@available(...)) {
Run Code Online (Sandbox Code Playgroud)

仅允许空格和换行符变化。是的,您可能会怀疑单个not(!)确实很复杂,但是您会在哪里划清界限?关于什么:

if ((todayIsTuesday() && @available(iOS 9.0, *)) 
    || (self.theWeatherIsNice && !@available(iOS 11.0, *)) {
Run Code Online (Sandbox Code Playgroud)

因此,只允许执行一条简单的语句,该语句仅强制编译器将代码分为两部分,并且始终始终只有一个部分可以运行:一个用于列出的OS,另一个用于其余的OS。当然,可以将“其余”再次细分else if。如果缺少,则只有else节可以自动生成,因此在编写时:

if (@available(...)) {
    someCode();
} // There is no else
Run Code Online (Sandbox Code Playgroud)

编译器也很高兴,因为它与

if (@available(...)) {
     someCode();
} else {
    // Nothing to do here
}
Run Code Online (Sandbox Code Playgroud)