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

时间:2019-01-15 17:03:23

标签: ios objective-c swift language-interoperability

尽管here苹果公司声明Swift available标志也应在objc中应用,但它对我不起作用。我在做什么错了?


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

@objc protocol Readable: AnyObject {...}

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

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

let tmp = Reader()

它返回错误:

  

“阅读器”仅在iOS 10.3或更高版本上可用

期待什么。


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

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

构建完成没有任何错误,而我期望与Swift中的错误相同。


我尝试用以下方式标记课程:

  • @available(iOS 11,*)
  • @available(iOS,已推出:10.3)

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

1 个答案:

答案 0 :(得分:1)

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

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

  • 调用缺少的弱链接函数将会崩溃
  • 读取或写入缺少的全局变量将导致崩溃
  • 使用缺少的类将是无操作,并且所有方法都将返回零

测试在运行时是否找到符号的旧方法只是将其与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的部署目标上可能不可用的符号,可能永远不会是编译时错误(默认错误级别)。