【问题标题】:Swift and Objc interoperability - availability not working only in objcSwift 和 Objc 互操作性 - 可用性不仅仅在 objc 中起作用
【发布时间】:2019-06-09 17:54:04
【问题描述】:

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


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

@objc protocol Readable: AnyObject {...}

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

所以让我们检查一下当我尝试在没有版本检查的 pre-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 中这些都不起作用(产生错误)。请帮忙?

【问题讨论】:

    标签: ios objective-c swift language-interoperability


    【解决方案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 中的部署目标上不可用的符号可能永远不会是编译时错误(在默认错误级别)。

    【讨论】:

    • 不应该至少产生一个警告..?因为对我来说它不在 objc 中。
    • @Vive,检查您的编译器调用是否包含-Wunguarded-availability-Wunguarded-availability-new 警告标志。您应该能够在项目的构建设置中找到控制它的设置,Apple Clang - 警告 - 所有语言部分,作为“无保障的可用性”。
    • -Wungarded-availability-new flag 只会对 macOS >= 10.13、iOS >= 11、watchOS >= 4 和 tvOS >= 11 中引入的未受保护的 API 发出警告(以避免对旧代码发出垃圾邮件警告)。
    • 我已经检查过了..我错了!我将unguarded availability 设置为YES,而它应该是YES (all versions)。问题已解决,谢谢!
    • @Vive 你的意思是设置YES (all versions) 时,在iOS 10.3 以下实例化Reader 时,Objective-C 代码会出现构建错误?
    猜你喜欢
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 2017-05-17
    相关资源
    最近更新 更多