否定 Objective-C 的 @available 关键字

Negating Objective-C's @available keyword

我想 运行 仅当当前设备的 iOS 版本低于指定的特定版本时 运行 一段代码 。 Apple 给出的代码示例如下所示:

if (@available(iOS 10.0, *)) {
  // iOS 10.0 and above
} else {
  // below 10.0
}

但是,在某些情况下,只有当当前 iOS 版本低于特定版本时,人们才想 运行 编写代码。我假设以下代码可以工作:

if (!@available(iOS 10.0, *)) {
  // below 10.0
}

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

@available does not guard availability here; use if (@available) instead

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

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

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

是否有另一种使用我所缺少的 @available 的预期方法?

You can define your own custom macros that you can use throughout your application. Example:-

#define isIOS11() ([[UIDevice currentDevice].systemVersion doubleValue]>= 11.0 && [[UIDevice currentDevice].systemVersion doubleValue] < 12.0)

#define SinceIOS9_2 ([[UIDevice currentDevice].systemVersion doubleValue]>= 4.2 && [[UIDevice currentDevice].systemVersion doubleValue] < 9.2)

像下面这样使用它:-

if (isIOS11()) {
    // Do something for iOS 11 
} else {
    // Do something iOS Versions below 11.0
}

如果这对你有用,请告诉我。

@available 的想法是您想使用仅在某些系统上可用的 API。对于其他系统,该功能要么在您的应用程序中缺失,要么您提供了替代功能。在不需要特定 OS 版本以外的任何代码的情况下,正确的使用方法是

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

原因是编译器有时必须对 @available 保护的代码执行一些额外的魔法,因此它需要清楚地识别这种情况。所以实际上它明确搜索

if (@available(...)) {

只允许空格和换行符的变化。是的,您可能会怀疑单个非 (!) 实际上一点也不复杂,但是您会在哪里划清界限呢?怎么样:

if ((todayIsTuesday() && @available(iOS 9.0, *)) 
    || (self.theWeatherIsNice && !@available(iOS 11.0, *)) {

因此只允许一个简单的语句,它只会强制编译器将代码分成两部分,并且总是只有一个部分 运行 肯定:一个用于列出的 OSes 和一个对于其余的。当然,"the rest"可以再细分,else if是允许的。只有 else 部分如果缺失可以自动生成,所以当你这样写时:

if (@available(...)) {
    someCode();
} // There is no else

编译器也很高兴,因为那是一样的

if (@available(...)) {
     someCode();
} else {
    // Nothing to do here
}
if (@available ...) {
   ...
} else {
   ...
}

是唯一允许的形式。它必须像那样,因为不同的规则适用于 if 部分和 else 部分。在 if 部分,您可以调用一个 SDK 中可用的方法,在 else 部分,它是来自另一个 SDK 的方法。同一个调用在一个分支中可能是合法的而在另一个分支中是非法的,或者在一个分支中被弃用而在另一个分支中不被推荐。