Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
#ifdef替换为Swift语言_Swift_Xcode_Preprocessor_Preprocessor Directive - Fatal编程技术网

#ifdef替换为Swift语言

#ifdef替换为Swift语言,swift,xcode,preprocessor,preprocessor-directive,Swift,Xcode,Preprocessor,Preprocessor Directive,在C/C++/Objective C中,可以使用编译器预处理器定义宏。 此外,可以使用编译器预处理器包含/排除部分代码 #ifdef DEBUG // Debug-only code #endif Swift中是否有类似的解决方案?没有Swift预处理器。(一方面,任意代码替换会破坏类型和内存安全。) 不过,Swift确实包含构建时配置选项,因此您可以有条件地包含特定平台或构建样式的代码,或者响应您使用-D编译器参数定义的标志。不过,与C不同的是,代码中有条件编译的部分必须是语法完整的

在C/C++/Objective C中,可以使用编译器预处理器定义宏。 此外,可以使用编译器预处理器包含/排除部分代码

#ifdef DEBUG
    // Debug-only code
#endif

Swift中是否有类似的解决方案?

没有Swift预处理器。(一方面,任意代码替换会破坏类型和内存安全。)

不过,Swift确实包含构建时配置选项,因此您可以有条件地包含特定平台或构建样式的代码,或者响应您使用
-D
编译器参数定义的标志。不过,与C不同的是,代码中有条件编译的部分必须是语法完整的。这本书有一节是关于这个的

例如:

#if os(iOS)
    let color = UIColor.redColor()
#else
    let color = NSColor.redColor()
#endif
是的,你能做到

在Swift中,您仍然可以使用“#if/#else/#endif”预处理器宏(尽管受约束更多),如所示。下面是一个例子:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif
现在,您必须在别处设置“DEBUG”符号。在“Swift编译器-自定义标志”部分的“其他Swift标志”行中进行设置。使用
-D DEBUG
条目添加调试符号

通常,您可以在调试或发布时设置不同的值

我在真实的代码中测试了它,它可以工作;不过,在操场上,人们似乎认不出它

你可以读我原来的帖子



重要提示:
-DDEBUG=1
不起作用。只有
-D调试
起作用。编译器似乎忽略了具有特定值的标志。

在许多情况下,您并不真正需要条件编译;您只需要可以打开和关闭的条件行为。为此,可以使用环境变量。这有一个巨大的优势,您实际上不必重新编译

您可以在方案编辑器中设置环境变量,并轻松地将其打开或关闭:

您可以使用NSProcessInfo检索环境变量:

    let dic = NSProcessInfo.processInfo().environment
    if dic["TRIPLE"] != nil {
        // ... do secret stuff here ...
    }
这里有一个真实的例子。我的应用程序只在设备上运行,因为它使用的是模拟器上不存在的音乐库。那么,如何在模拟器上为我没有的设备拍摄屏幕快照呢?没有这些屏幕截图,我无法提交到AppStore


我需要假数据和不同的处理方式。我有两个环境变量:一个是打开时,告诉应用程序在我的设备上运行时从真实数据生成假数据;另一个,当打开时,在模拟器上运行时使用假数据(而不是丢失的音乐库)。由于“方案编辑器”(Scheme editor)中的“环境变量”(environment variable)复选框,可以轻松地打开/关闭这些特殊模式。另外,我不能在我的应用商店构建中意外使用它们,因为归档没有环境变量

从Swift 4.1开始,如果您只需要检查代码是使用调试配置还是发布配置生成的,您可以使用内置功能:

  • \u isDebugAssertConfiguration()
    (当优化设置为
    -Onone
    时为true)
  • \u isReleaseAssertConfiguration()
    (当优化设置为
    -O
    时为真)(在Swift 3+上不可用)
  • \u isFastAssertConfiguration()
    (当优化设置为
    -选中时为true
e、 g

与预处理器宏相比

  • ✓ 使用它不需要定义自定义的
    -D DEBUG
    标志
  • ~它实际上是根据优化设置定义的,而不是Xcode构建配置
  • ✗ 未记录,这意味着该函数可以在任何更新中删除(但它应该是AppStore安全的,因为优化器会将其转换为常量)

    • 这些曾经,但是,未来命运未卜
  • ✗ 在if/else中使用将始终生成“永远不会执行”警告

如中所述

Swift编译器不包括预处理器。相反,它利用编译时属性、构建配置和语言特性来实现相同的功能。因此,预处理器指令不会在Swift中导入

我已通过使用自定义构建配置实现了我想要的:

  • 转到项目/选择目标/生成设置/搜索自定义标志
  • 对于所选目标,使用-D前缀(不带空格)为调试和发布设置自定义标志
  • 针对您的每个目标执行上述步骤
  • 以下是检查目标的方法:

    #if BANANA
        print("We have a banana")
    #elseif MELONA
        print("Melona")
    #else
        print("Kiwi")
    #endif
    


    使用Swift 2.2对Xcode 8进行了测试:

    a) 使用
    -D
    前缀的自定义标志可以正常工作,但是

    b) 更简单的使用:

    在Xcode 8中有一个新的部分:“活动编译条件”, 已包含两行,用于调试和发布


    只需添加您的define而不使用
    -D

    Xcode 8对
    ifdef
    进行了重大更改。i、 e使用活动编译条件

    请参阅中的构建和链接

    新生成设置

    新设置:
    SWIFT\u活动\u编译\u条件

    “Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.
    
    以前,我们必须在其他_SWIFT_标志下声明您的条件编译标志,记住在设置前加“-D”。例如,要使用MYFLAG值有条件地编译:

    #if MYFLAG1
        // stuff 1
    #elseif MYFLAG2
        // stuff 2
    #else
        // stuff 3
    #endif
    
    要添加到设置中的值
    -DMYFLAG

    现在我们只需要将值MYFLAG传递给新设置。是时候移动所有这些条件编译值了

    有关Xcode 8中更快速的构建设置功能,请参阅以下链接:

    Xcode 8及以上 使用生成设置/Swift编译器-自定义标志中的活动编译条件设置

    • 这是用于将条件编译标志传递给Swift编译器的新生成设置
    • 简单地添加如下标志:
      ALPHA
      BETA
      #if MYFLAG1
          // stuff 1
      #elseif MYFLAG2
          // stuff 2
      #else
          // stuff 3
      #endif
      
      #if ALPHA
          //
      #elseif BETA
          //
      #else
          //
      #endif
      
      #if DEBUG
          let isDebug = true
      #else
          let isDebug = false
      #endif
      
      let isDebug: Bool = {
          var isDebug = false
          // function with a side effect and Bool return value that we can pass into assert()
          func set(debug: Bool) -> Bool {
              isDebug = debug
              return isDebug
          }
          // assert:
          // "Condition is only evaluated in playgrounds and -Onone builds."
          // so isDebug is never changed to true in Release builds
          assert(set(debug: true))
          return isDebug
      }()
      
      func Log(_ str: String) { 
          assert(DebugLog(str)) 
      }
      func DebugLog(_ str: String) -> Bool { 
          print(str) 
          return true
      }
      
      let iterations = 100_000_000
      let time1 = CFAbsoluteTimeGetCurrent()
      for i in 0 ..< iterations {
          Log ("⧉ unarchiveArray:\(fileName) memoryTime:\(memoryTime) count:\(array.count)")
      }
      var time2 = CFAbsoluteTimeGetCurrent()
      print ("Log: \(time2-time1)" )
      
      Log: 0.0
      
      func executeInProduction(_ block: () -> Void)
      {
          #if !DEBUG
              block()
          #endif
      }
      
      executeInProduction {
          Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug
      }
      
      #if !DEBUG
          Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds
      #endif
      
       #if Live
          print("Live")
          #else
          print("debug")
          #endif
      
      #if DEBUG
      #endif
      
      #if DEVELOP
          //
      #elseif PRODCTN
          //
      #else
          //
      #endif
      
      func inDebugBuilds(_ code: () -> Void) {
          assert({ code(); return true }())
      }
      
      #if DEBUG
          let a = 2
      #else
          let a = 3
      #endif
      
      #if !RELEASE
          let a = 2
      #else
          let a = 3
      #endif
      
      #if os(macOS) /* Checks the target operating system */
      
      #if canImport(UIKit) /* Check if a module presents */
      
      #if swift(<5) /* Check the Swift version */
      
      #if targetEnvironment(simulator) /* Check envrionments like Simulator or Catalyst */
      
      #if compiler(<7) /* Check compiler version */
      
      #if DEBUG
      print("Debug mode")
      #endif