Remove println() for release version iOS Swift

前端 未结 19 1379
被撕碎了的回忆
被撕碎了的回忆 2020-11-29 15:55

I would like to globally ignore all println() calls in my Swift code if I am not in a Debug build. I can\'t find any robust step by step instructions for this a

相关标签:
19条回答
  • 2020-11-29 16:33

    Swift 5

    Simply make a new file in your project and paste this code in:

    func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
        #if DEBUG
        items.forEach {
            Swift.print($0, separator: separator, terminator: terminator)        
        }
        #endif
    }
    

    This function signature matches the default Swift one so it "overwrites" the function in your project. If needed you can still access the original by using Swift.print().

    Once you've added the code above, keep using print() the as usual and it will only print in debug builds.

    Note: Doing the forEach to print each item gets rid of annoying array brackets around the print statements that show up if you just pass items straight into Swift.print().

    For anyone relatively new to Swift you may wonder what the heck $0 is. It just represents the first argument passed into the forEach block. The forEach statement could also be written like this:

    items.forEach { item in
        Swift.print(item, separator: separator, terminator: terminator)        
    }
    

    Lastly if you're interested, the Swift declaration of print looks like this:

    public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
    

    My answer above mirrors the exact Swift implementation - although I never print more than one thing or change separator/terminators. But who knows, you may want to.

    0 讨论(0)
  • 2020-11-29 16:33

    Tested with Swift 2.1 & Xcode 7.1.1

    There's an easy way to exclude all print statements from release versions, once you know that empty functions are removed by the Swift compiler.

    Side note : In the era of Objective-C, there was a pre-parser which could be used to remove NSLog statements before the compiler kicked in, like described in my answer here. But since Swift no longer has a pre-parser this approach is no longer valid.

    Here's what I use today as an advanced and easily configurable log function, without ever having to worry about removing it in release builds. Also by setting different compiler flags, you can tweak the information that is logged as needed.

    You can tweak the function as needed, any suggestion to improve it is welcome!

    // Gobal log() function
    //
    // note that empty functions are removed by the Swift compiler -> use #if $endif to enclose all the code inside the log()
    // these log() statements therefore do not need to be removed in the release build !
    //
    // to enable logging
    //
    // Project -> Build Settings -> Swift Compiler - Custom flags -> Other Swift flags -> Debug
    // add one of these 3 possible combinations :
    //
    //      -D kLOG_ENABLE
    //      -D kLOG_ENABLE -D kLOG_DETAILS
    //      -D kLOG_ENABLE -D kLOG_DETAILS -D kLOG_THREADS
    //
    // you can just call log() anywhere in the code, or add a message like log("hello")
    //
    func log(message: String = "", filePath: String = #file, line: Int = #line, function: String = #function) {
                #if kLOG_ENABLE
    
                #if kLOG_DETAILS
    
                var threadName = ""
                #if kLOG_THREADS
                    threadName = NSThread.currentThread().isMainThread ? "MAIN THREAD" : (NSThread.currentThread().name ?? "UNKNOWN THREAD")
                    threadName = "[" + threadName + "] "
                #endif
    
                let fileName = NSURL(fileURLWithPath: filePath).URLByDeletingPathExtension?.lastPathComponent ?? "???"
    
                var msg = ""
                if message != "" {
                    msg = " - \(message)"
                }
    
                NSLog("-- " + threadName + fileName + "(\(line))" + " -> " + function + msg)
            #else
                NSLog(message)
            #endif
        #endif
    }
    

    Here's where you set the compiler flags :

    An example output with all flags on looks like this :

       2016-01-13 23:48:38.026 FoodTracker[48735:4147607] -- [MAIN THREAD] ViewController(19) -> viewDidLoad() - hello
    

    The code with the log() looks like this :

        override func viewDidLoad() { log("hello")
        super.viewDidLoad()
    
       // Handle the text field's user input through delegate callbacks
       nameTextField.delegate = self
    }
    
    0 讨论(0)
  • 2020-11-29 16:33

    This works for me (add this as a global function in the project)

    func print(_ items: Any...) {
        #if DEBUG
            Swift.print(items[0])
        #endif
    }
    
    0 讨论(0)
  • 2020-11-29 16:36

    You can also use a breakpoint, set it to continue after evaluation, and write the print message in the breakpoint!

    0 讨论(0)
  • 2020-11-29 16:36

    for my solution i make it simple

    import UIKit
    
    class DLog: NSObject {
    
       init(title:String, log:Any) {
           #if DEBUG
               print(title, log)
           #endif
    
       }
    
    }
    

    then to show it just call

    _ = DLog(title:"any title", log:Any)
    
    0 讨论(0)
  • 2020-11-29 16:37

    Updated for Swift 4.x:

    With Swift 2.0/3.0 and Xcode 7/8 now out of beta, there have been some changes to how you disable the print function in release builds.

    There are some important points mentioned by @matt and @Nate Birkholz above that are still valid.

    1. The println() function has been replaced by print()

    2. To use the #if DEBUG macro then you have to define the "Swift Compiler - Custom Flags -Other Flags" to contain the value -D DEBUG

    3. I would recommend overriding the Swift.print() function in the global scope so that you can use the print() function as normal in your code, but it will remove output for non-debug builds. Here is a function signature that you can add at the global scope to do this in Swift 2.0/3.0:

      func print(items: Any..., separator: String = " ", terminator: String = "\n") {
      
          #if DEBUG
      
          var idx = items.startIndex
          let endIdx = items.endIndex
      
          repeat {
              Swift.print(items[idx], separator: separator, terminator: idx == (endIdx - 1) ? terminator : separator)
              idx += 1
          }
          while idx < endIdx
      
          #endif
      }
      

    Note: We have set the default separator to be a space here, and the default terminator to be a newline. You can configure this differently in your project if you would like.

    Hope this helps.

    Update:

    It is usually preferable to put this function at the global scope, so that it sits in front of Swift's print function. I find that the best way to organize this is to add a utility file to your project (like DebugOptions.Swift) where you can place this function at the global scope.

    As of Swift 3 the ++ operator will be deprecated. I have updated the snippet above to reflect this change.

    0 讨论(0)
提交回复
热议问题