【问题标题】:What's the Swift equivalent of Objective-C's "#ifdef __IPHONE_11_0"?Objective-C 的“#ifdef __IPHONE_11_0”的 Swift 等价物是什么?
【发布时间】:2017-11-09 11:55:27
【问题描述】:

我想使用 Xcode 9 将 iOS 11 代码添加到我的项目中,同时保留使用仅支持 iOS 10 的 Xcode 8 编译项目的选项。

在 Objective-C 中,我可以通过使用预处理器指令来检查是否定义了 __IPHONE_11_0。如果我使用早于 iOS 11 的 Base SDK 进行编译,这将隐藏代码。像这样:

#ifdef __IPHONE_11_0
    if (@available(iOS 11.0, *)) {
        self.navigationController.navigationBar.prefersLargeTitles = YES;
    }
#endif

有没有办法在 Swift 中做到这一点?

if #available(iOS 11.0, *) 不起作用,因为这是运行时检查。

【问题讨论】:

    标签: swift xcode macros versioning


    【解决方案1】:

    iOS 11 SDK 附带 Swift 3.2(或 Swift 4),因此您可以使用 Swift 版本检查来完成同样的事情:

    #if swift(>=3.2)
        if #available(iOS 11.0, *) {
            …
        }
    #endif
    

    【讨论】:

    • 如何在 obj-C 项目中使用它?编译器错误是“未定义类似函数的宏'swift'”?谢谢
    • @Jerome 它不能。
    【解决方案2】:

    这是苹果建议的解决方案:

    if #available(iOS 11.0, *) {
        // iOS 11 specific stuff here
    } else {
        // non iOS 11 stuff here
    }
    

    请参考this resource(观看 6:50 的视频了解更多详情)

    【讨论】:

    • 这是一个方法的内部。我认为 op 正在尝试找出仅适用于 iOS 11 或更高版本的方法。
    • 是的,另一个答案(Carly)在函数之外解决了这个问题。将 @available(iOS 11.0, *) 放在函数之前,不带 if 语句。
    【解决方案3】:

    如果你想把条件放在函数之外,你可以像下面那样做。

    @available(iOS 11.0, *)
    func functionName() {
     // function contents
    }
    

    【讨论】:

      【解决方案4】:

      我明白了。我有一台我喜欢使用的旧 Mac,它对于 Xcode 9 来说太旧了,所以我有时也希望能够在 Xcode 8 下编译我的项目。

      但是,如果您只想同时支持 iOS 10 和 iOS 11,那么简单的方法就是将 Xcode 目标的最低 SDK 设置为 10.0,并始终使用 iOS 11 SDK 进行编译。在这种情况下,Swift 会为你工作,并且会给你语法错误,除非你正确使用 if #available(iOS 11.0, *) {

      您仍然可以在 iOS 10 和 iOS 11 下进行测试,并且无需为 Xcode 8 操心。

      从 Xcode 8 的角度来看,您正在尝试编译来自未来的源代码。 Xcode 8 没有好的解决方案。

      接下来,解决方案如下:

      在 Xcode 9.3 (Swift 4.1) 中,你可以说:

      #if canImport(MagiciOS12Kit)
        if #available(iOS 12.0, *) {
           MagiciOS12Class.standard.method()
        }
      #endif
      

      您的代码仍将在 Xcode 9.3 下编译,但会跳过需要假设 Xcode 10.0 或更高版本的未来内容。

      #if canImport(moduleName) 仅在 Swift 4.1 中添加,Xcode 8 无法处理。但即使这样也只适用于苹果未来添加的整个模块。如果 Apple 只是使用新方法扩展现有类,如在您的 navigationController.navigationBar.prefersLargeTitles 中,您仍然无法直接测试 prefersLargeTitles,但您可以找到Apple 与 prefersLargeTitles 同时引入的另一个框架,并使用 #if canImport(…) 检查该框架是否存在。

      【讨论】:

      • 如何在objective-c中使用canImport?
      • 致 Karim:Objective-C 并没有真正以同样的方式使用模块。在 Objective-C 中,在项目级别,您包含一个框架,但将其设置为“弱”而不是必需的。在运行时,您可以使用if (NSClassFromString(@"MagiciOS!2Class")) {…} 检查它是否存在于运行代码的特定设备上。
      【解决方案5】:

      您可以通过执行以下功能来实现

      @available(iOS 11.0, *)
      func myFunction() {
       // function defination 
      }
      

      或者如果你想检查内部函数写这个

      if #available(iOS 11.0, *) {
          // iOS 11 specific stuff here
      } else if #available(iOS 10.0, *) {
         // iOS 10 specific stuff here
      } else {
          // non iOS 11 & 10 stuff here
      }
      

      【讨论】:

        猜你喜欢
        • 2014-07-28
        • 2023-03-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-25
        相关资源
        最近更新 更多