44

The code is:

let redColor = "\u{001B}[0;31m"
var message = "Some Message"
print(redColor + message)  //This doesn't work
print("\(redColor)\(message)") //This also doesn't work

and the output would look like this:

[0;31mSome Message

I've also read this post: Color ouput with Swift command line tool, and it doesn't seem to work.

I don't want to use libraries.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Zonily Jame
  • 5,053
  • 3
  • 30
  • 56
  • 5
    As [mentioned in the linked-to Q&A](http://stackoverflow.com/questions/27807925/color-ouput-with-swift-command-line-tool#comment50249685_27808423), setting the color works when the program is run in a Terminal window, but *not* in the Xcode console. – Martin R Nov 14 '16 at 07:42
  • oh god. Seriously?. I guess I'll just use emoji's to mark my logs then. – Zonily Jame Nov 14 '16 at 07:49
  • 6
    Also confirmed here http://stackoverflow.com/questions/9005769/any-way-to-print-in-color-with-nslog: *"... as Xcode debugging console doesn't seem to support coloring."* – Martin R Nov 14 '16 at 07:52
  • ok thanks man. should I keep this question open or should I close it? – Zonily Jame Nov 14 '16 at 07:56
  • Xcode's terminal window does not support coloring. Its `$TERM` value is nil. There's no way to have colors in the Xcode's debugger area. *But* you can attach another terminal as output (in Xcode's prefs) and there, the output will support colors. – Eric Aya Mar 28 '17 at 12:37
  • @ZonilyJame If you choose to close it, don't forget to validate my answer please. – Danyl Apr 02 '17 at 20:10
  • 1
    @DanylS I won't close it but I'll place you as the answer, we never know if there might be a change for the next iterations of Xcode – Zonily Jame Apr 04 '17 at 07:48
  • Ok, alright @ZonilyJame. – Danyl Apr 04 '17 at 08:13
  • Why don't give it a try: https://github.com/zhihuitang/SwiftMagic – DàChún Jan 15 '18 at 15:54

7 Answers7

59

Xcode doesn't support console coloring since Xcode 8.

But Since Xcode is fully unicode compatible, you can use emojis instead! for example you can use You can use ⚠️ for warning messages and for error messages. (like the Xcode itself)

Or simply use these note books as a color:

: error message
: warning message
: ok status message
: action message
: canceled status message
: Or anything you like and want to recognize immediately by color

for example:

print("⚠️", "Touch is not disabled as expected")

Bones

Using this method will help you to find the logs in the source code as fast as ⚡️ by a simple eye scan:

Demo

And you can search for them to let the Xcode take you there. Take a look at this result comparison:

Custom emoji search

emoji search

vs

Word search

word search

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
36

Nowadays, Xcode debugging console doesn't support coloring.

Danyl
  • 2,012
  • 3
  • 19
  • 40
6

Adding to @Mojtaba's answer, you can use this for automating logging:

enum LogType: String{
case error
case warning
case success
case action
case canceled
}


class Logger{

 static func log(_ logType:LogType,_ message:String){
        switch logType {
        case LogType.error:
            print("\n Error: \(message)\n")
        case LogType.warning:
            print("\n Warning: \(message)\n")
        case LogType.success:
            print("\n Success: \(message)\n")
        case LogType.action:
            print("\n Action: \(message)\n")
        case LogType.canceled:
            print("\n Cancelled: \(message)\n")
        }
    }

}

You can use it this way:

Logger.log(.error, "Invalid Credit Information")
Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
Lenda
  • 124
  • 1
  • 9
2

As @LeslieGodwin mentioned, the XcodeColors Xcode plugin adds color support to the Xcode console (for Xcode versions below 8)

Mojtaba Hosseini
  • 95,414
  • 31
  • 268
  • 278
ThomasW
  • 16,981
  • 4
  • 79
  • 106
2

Adding my own contribution:

struct Logger {
    /// Type of logs available
    enum LogType: String {
        /// To log a message
        case debug
        /// To log a warning
        case warning
        /// To log an error
        case error
    }
    
    /// Logs a debug message
    /// - Parameter message: Message to log
    /// - Parameter file: File that calls the function
    /// - Parameter line: Line of code from the file where the function is call
    /// - Parameter function: Function that calls the functon
    /// - Returns: The optional message that was logged
    @discardableResult
    static func d(message: String, file: String = #file, line: Int = #line, function: String = #function) -> String{
        return log(type: .debug, message: message, file: file, line: line, function: function)
    }
    
    /// Logs a warning message
    /// - Parameter message: Message to log
    /// - Parameter file: File that calls the function
    /// - Parameter line: Line of code from the file where the function is call
    /// - Parameter function: Function that calls the functon
    /// - Returns: The optional message that was logged
    @discardableResult
    static func w(message: String, file: String = #file, line: Int = #line, function: String = #function) -> String{
        return log(type: .warning, message: message, file: file, line: line, function: function)
    }
    
    /// Logs an error message
    /// - Parameter message: Message to log
    /// - Parameter file: File that calls the function
    /// - Parameter line: Line of code from the file where the function is call
    /// - Parameter function: Function that calls the functon
    /// - Returns: The optional message that was logged
    @discardableResult
    static func e(message: String, file: String = #file, line: Int = #line, function: String = #function) -> String{
        return log(type: .error, message: message, file: file, line: line, function: function)
    }
    
    /// Logs an message
    /// - Parameter logType: Type of message to log
    /// - Parameter message: Message to log
    /// - Parameter file: File that calls the function
    /// - Parameter line: Line of code from the file where the function is call
    /// - Parameter function: Function that calls the functon
    /// - Returns: The optional message that was logged
    @discardableResult
    static func log(type logType: LogType = .debug, message: String, file: String = #file, line: Int = #line, function: String = #function) -> String{
        var logMessage = ""
        
        switch logType{
        case .debug:
            logMessage += ""
        case .warning:
            logMessage += ""
        case .error:
            logMessage += ""
        }
        
        let fileName = file.components(separatedBy: "/").last ?? ""
        logMessage += " \(fileName) -> LINE: \(line) -> \(function) => \(message)"
        
        print(logMessage)
        return logMessage
    }

}

You can always change the icons using "crtl+cmd+space"

Reimond Hill
  • 4,278
  • 40
  • 52
1

If you're looking for a replacement color logging within Xcode see this new swift-log feature that I created.

https://github.com/nneuberger1/swift-log-console-colors

It uses the new standard swift-log compatible library.

The output will look like this if passing in .cool

2021-05-09T16:13:30-0500  debug thingsAboveAdmin : Testing log levels..
2021-05-09T16:13:30-0500 ℹ️ info thingsAboveAdmin : Testing log levels..
2021-05-09T16:13:30-0500  notice thingsAboveAdmin : Testing log levels..
2021-05-09T16:13:30-0500 ⚠️ warning thingsAboveAdmin : Testing log levels..
2021-05-09T16:13:30-0500 ⚡ critical thingsAboveAdmin : Testing log levels..
2021-05-09T16:13:30-0500  error thingsAboveAdmin : Testing log levels..

The output will look like this if passing in .rainbow

2021-05-09T16:17:07-0500  debug thingsAboveAdmin : Testing log levels..
2021-05-09T16:17:07-0500  info thingsAboveAdmin : Testing log levels..
2021-05-09T16:17:07-0500  notice thingsAboveAdmin : Testing log levels..
2021-05-09T16:17:07-0500  warning thingsAboveAdmin : Testing log levels..
2021-05-09T16:17:07-0500  critical thingsAboveAdmin : Testing log levels..
2021-05-09T16:17:07-0500  error thingsAboveAdmin : Testing log levels..
Nick N
  • 984
  • 9
  • 22
1

Taking Mojtaba Hosseini's answer, I have incorporated it into a Log class to have very detailed logging:

The class is as follows:

import Foundation
import OSLog


class Log {
    #if DEBUG
    static let logLevel = "deiwv"
    #else
    static let logLevel = "e"
    #endif
    static var subsystem = Bundle.main.bundleIdentifier ?? ""
    static var flags = [  "e" : "",
                        "w" : "",
                        "i" : "",
                        "d" : "",
                        "v" : ""
                  ]
    
    static func setup(_ fileStr: String, _ funcStr: String, _ line: Int, _ level: String) -> String {
        var fileName = fileStr.components(separatedBy: "/").last ?? ""
        fileName = fileName.components(separatedBy:".").first ?? ""
        fileName = fileName.padding(toLength: 20, withPad: " ", startingAt: 0)
        let funcString = funcStr.padding(toLength: 10, withPad: " ", startingAt: 0)
        let lineNum = "\(line)".padding(toLength: 4, withPad: " ", startingAt: 0)
        let flag = flags[level] ?? ""
        return "\(flag)\(level.uppercased()) \(fileName):\(funcString):\(lineNum)"
    }
    
    static func i(_ msg: String, fileStr: String = #file, funcStr: String = #function, line: Int = #line) {
        if(logLevel.contains("i")) {
            Logger(subsystem: subsystem, category: setup(fileStr, funcStr, line, "i")).info("\(msg)")
        }
    }
    static func e(_ msg: String, fileStr: String = #file, funcStr: String = #function, line: Int = #line) {
        if(logLevel.contains("e")) {
            Logger(subsystem: subsystem, category: setup(fileStr, funcStr, line, "e")).error("\(msg)")
        }
    }
    static func d(_ msg: String, fileStr: String = #file, funcStr: String = #function, line: Int = #line) {
        if(logLevel.contains("d")) {
            Logger(subsystem: subsystem, category: setup(fileStr, funcStr, line, "d")).debug("\(msg)")
        }
    }
    static func w(_ msg: String, fileStr: String = #file, funcStr: String = #function, line: Int = #line) {
        if(logLevel.contains("w")) {
            Logger(subsystem: subsystem, category: setup(fileStr, funcStr, line, "w")).warning("\(msg)")
        }
    }
    static func v(_ msg: String, fileStr: String = #file, funcStr: String = #function, line: Int = #line) {
        if(logLevel.contains("v")) {
            Logger(subsystem: subsystem, category: setup(fileStr, funcStr, line, "v")).log("\(msg)")
        }
    }
}

This allows logging i.e. as follows:

Log.i("This is the logged comment")

or

Log.e("This is an error")

Output is tagged and shows the filename, the function name and the line number where the logging occurs, making it much easier to find something in a larger project:

2023-04-12 19:03:22.006185+0100 OOHSystem[34170:6047034] [I InitialViewControlle:viewDidLoa:27  ] Loaded
2023-04-12 19:03:22.006766+0100 OOHSystem[34170:6047034] [I InitialViewControlle:viewWillAp:33  ] Started
2023-04-12 19:03:22.007867+0100 OOHSystem[34170:6047034] [I InitialViewControlle:viewWillAp:47  ] Called from startup
2023-04-12 19:03:22.078324+0100 OOHSystem[34170:6047034] [I UIDeviceExtensions  :UIDevice  :110 ] identfied: arm64
2023-04-12 19:03:22.079177+0100 OOHSystem[34170:6047034] [V Globals             :token     :17  ] 3ae51797ac5a8619010352's

By default, production only logs errors but of course that is easy to configure.

There may be better or more elegant ways of achieving this, but it works for me.