Swift 和 Objc 互操作性 - 可用性不仅仅在 objc 中工作

Swift and Objc interoperability - availability not working only in objc

虽然 here Apple 声明 Swift available 标志也应应用于 objc,但它对我不起作用。我做错了什么?


我在 Swift 个文件中有以下声明:

@objc protocol Readable: AnyObject {...}

@available(iOS 10.3, *)
@objc class Reader: NSObject, Readable {...}

因此,让我们检查一下当我尝试在 ios-10 之前的项目中初始化它而不进行版本检查时它是否会产生错误。如果我在 Swift 中编写以下代码:

let tmp = Reader()

它returns一个错误:

'Reader' is only available on iOS 10.3 or newer

预期结果。


但是,如果我在 objc 中编写以下代码:

// if (@available(iOS 10.3, *)) { // commeted out to test if it succeeds without version check
    Reader *tmp = [[Reader alloc] init];
// }

构建完成,没有任何错误,而我预计会出现与 Swift.

中相同的错误

我尝试用以下方式标记 class:

这些在 objc 中都不起作用(产生错误)。有什么帮助吗?

Objective-C 拥有 __attribute__((availability)) 的时间比拥有 @available 的时间长。为了使其工作,Objective-C 编译器弱链接部署目标上不可用的符号。这意味着编译总是成功,并且启动你的应用程序成功,但如果符号不可用,则该符号在运行时将为 NULL。

取决于它是什么,当您尝试使用它时,您或多或少会得到优雅的降级:

  • 调用缺少的弱链接函数将会崩溃
  • 读取或写入丢失的全局变量将会崩溃
  • 使用缺少的 class 将是空操作,所有方法都将 return 归零

在运行时测试是否找到符号的旧方法只是将它与 NULL 进行比较:

NS_AVAILABLE_MAC(...) @interface Foo @end
int bar NS_AVAILABLE_MAC(...);
int baz(int frob) NS_AVAILABLE_MAC(...);

if ([Foo class]) { /* Foo is available */ }
if (&bar) { /* bar is available */ }
if (&baz) { /* baz is available */ }

你的情况:

Reader *tmp = [[Reader alloc] init];

tmp 将是 nil,因为这与 [[nil alloc] init].

相同

@available 指令最近才被添加到 Objective-C。现在可以像在 Swift 中使用 #available 一样在 Objective-C 中使用 @available。但是,为了保持向后兼容性,尝试使用可能在 Objective-C.

中的部署目标上不可用的符号可能永远不会是编译时错误(在默认错误级别)