Skip to content

Instantly share code, notes, and snippets.

@DaveWoodCom
Created April 16, 2015 07:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DaveWoodCom/71fbb90ca58fd058bf97 to your computer and use it in GitHub Desktop.
Save DaveWoodCom/71fbb90ca58fd058bf97 to your computer and use it in GitHub Desktop.
An XCGLogDestination that adds the logs to a UITextView
extension XCGLogger {
public class XCGTextViewLogDestination: XCGLogDestinationProtocol, DebugPrintable {
public var owner: XCGLogger
public var identifier: String
public var outputLogLevel: XCGLogger.LogLevel = .Debug
public var showThreadName: Bool = false
public var showFileName: Bool = true
public var showLineNumber: Bool = true
public var showLogLevel: Bool = true
public var textView: UITextView
public init(textView: UITextView, owner: XCGLogger, identifier: String = "") {
self.textView = textView
self.owner = owner
self.identifier = identifier
}
public func processLogDetails(logDetails: XCGLogDetails) {
var extendedDetails: String = ""
if showThreadName {
extendedDetails += "[" + (NSThread.isMainThread() ? "main" : (NSThread.currentThread().name != "" ? NSThread.currentThread().name : String(format:"%p", NSThread.currentThread()))) + "] "
}
if showLogLevel {
extendedDetails += "[" + logDetails.logLevel.description() + "] "
}
if showFileName {
extendedDetails += "[" + logDetails.fileName.lastPathComponent + (showLineNumber ? ":" + String(logDetails.lineNumber) : "") + "] "
}
else if showLineNumber {
extendedDetails += "[" + String(logDetails.lineNumber) + "] "
}
var formattedDate: String = logDetails.date.description
if let dateFormatter = owner.dateFormatter {
formattedDate = dateFormatter.stringFromDate(logDetails.date)
}
var fullLogMessage: String = "\(formattedDate) \(extendedDetails)\(logDetails.functionName): \(logDetails.logMessage)\n"
textView.text = textView.text + fullLogMessage
}
public func processInternalLogDetails(logDetails: XCGLogDetails) {
var extendedDetails: String = ""
if showLogLevel {
extendedDetails += "[" + logDetails.logLevel.description() + "] "
}
var formattedDate: String = logDetails.date.description
if let dateFormatter = owner.dateFormatter {
formattedDate = dateFormatter.stringFromDate(logDetails.date)
}
var fullLogMessage: String = "\(formattedDate) \(extendedDetails): \(logDetails.logMessage)\n"
textView.text = textView.text + fullLogMessage
}
// MARK: - Misc methods
public func isEnabledForLogLevel (logLevel: XCGLogger.LogLevel) -> Bool {
return logLevel >= self.outputLogLevel
}
// MARK: - DebugPrintable
public var debugDescription: String {
get {
return "XCGTextViewLogDestination: \(identifier) - LogLevel: \(outputLogLevel.description()) showThreadName: \(showThreadName) showLogLevel: \(showLogLevel) showFileName: \(showFileName) showLineNumber: \(showLineNumber)"
}
}
}
}
@DaveWoodCom
Copy link
Author

Add this log destination to your logger like this:

log.addLogDestination(XCGLogger.XCGTextViewLogDestination(textView: textView, owner: log, identifier: "com.cerebralgardens.xcglogger.logdestination.textview"))

@mabril
Copy link

mabril commented Apr 16, 2015

Nice! Thanks!

@kubanaltan
Copy link

I used your example code in my OSX project. I just replaced UITextView with NSTextView, and it worked for me :) Now my code both logs to my app window and file. However, I was just a bit suspicious with line:

textView.text = textView.text + fullLogMessage

So I extended NSTextView with an appendText method:
textView.appendText(fullLogMessage)

The code for appendText extension is:

extension NSTextView {
func appendText(line: String) {

    // Set font type
    let font = NSFont(name: "Courier", size: 12)

    //Set font color
    let color = NSColor(white: 0.2, alpha: 1.0)

    // Set attributes
    let attrDict = [NSFontAttributeName: font!,
                    NSForegroundColorAttributeName: color]

    let astring = NSAttributedString(string: "\(line)", attributes: attrDict)
    self.textStorage?.appendAttributedString(astring)

    let loc = self.string?.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)

    // Scroll to end
    let range = NSRange(location: loc!, length: 0)
    self.scrollRangeToVisible(range)
}

}

@winzig
Copy link

winzig commented Jul 2, 2015

This helped me out, thanks. FWIW, tried running this on iOS 9 beta 2 device, and had fatal crash at line 46:

function signature specialization <Arg[0] = Exploded> of ext.iATN.XCGLogger.XCGLogger.XCGTextViewLogDestination.processLogDetails (ext.iATN.XCGLogger.XCGLogger.XCGTextViewLogDestination)(XCGLogger.XCGLogDetails) -> ()

@horseshoe7
Copy link

I've updated this for the latest version (4.0.0) in Swift

extension XCGLogger {
    
    public class XCGTextViewLogDestination: DestinationProtocol {
        
        public var owner: XCGLogger?
        public var identifier: String
        public var outputLevel: XCGLogger.Level = .debug
        
        public var showThreadName: Bool = false
        public var showFileName: Bool = true
        public var showLineNumber: Bool = true
        public var showLogLevel: Bool = true
        
        public var haveLoggedAppDetails: Bool = false
        public var formatters: [LogFormatterProtocol]? = []
        public var filters: [FilterProtocol]? = []
        
        public var textView: UITextView
        
        public init(textView: UITextView, owner: XCGLogger, identifier: String = "") {
            self.textView = textView
            self.owner = owner
            self.identifier = identifier
        }
        
        public func process(logDetails: LogDetails) {
            var extendedDetails: String = ""
            
            if showThreadName {
                extendedDetails += "[" + (Thread.isMainThread ? "main" : (Thread.current.name! != "" ? Thread.current.name! : String(format:"%p", Thread.current))) + "] "
            }
            
            if showLogLevel {
                extendedDetails += "[" + logDetails.level.description + "] "
            }
            
            if showFileName {
                let filename = NSURL(fileURLWithPath: logDetails.fileName).lastPathComponent!
                extendedDetails += "[" + filename + (showLineNumber ? ":" + String(logDetails.lineNumber) : "") + "] "
            }
            else if showLineNumber {
                extendedDetails += "[" + String(logDetails.lineNumber) + "] "
            }
            
            var formattedDate: String = logDetails.date.description
            if let dateFormatter = owner!.dateFormatter {
                formattedDate = dateFormatter.string(from: logDetails.date)
            }
            
            let fullLogMessage: String =  "\(formattedDate) \(extendedDetails)\(logDetails.functionName): \(logDetails.message)\n"
            
            textView.text = textView.text + fullLogMessage
        }
        
        public func processInternal(logDetails: LogDetails) {
            var extendedDetails: String = ""
            if showLogLevel {
                extendedDetails += "[" + logDetails.level.description + "] "
            }
            
            var formattedDate: String = logDetails.date.description
            if let dateFormatter = owner!.dateFormatter {
                formattedDate = dateFormatter.string(from: logDetails.date)
            }
            
            let fullLogMessage: String =  "\(formattedDate) \(extendedDetails): \(logDetails.message)\n"
            
            textView.text = textView.text + fullLogMessage
        }
        
        // MARK: - Misc methods
        public func isEnabledFor(level: XCGLogger.Level) -> Bool {
            return level >= self.outputLevel
        }
        
        // MARK: - DebugPrintable
        public var debugDescription: String {
            get {
                return "XCGTextViewLogDestination: \(identifier) - LogLevel: \(outputLevel.description) showThreadName: \(showThreadName) showLogLevel: \(showLogLevel) showFileName: \(showFileName) showLineNumber: \(showLineNumber)"
            }
        }
    }
  }

@horseshoe7
Copy link

And to add it:

log.add(destination: XCGLogger.XCGTextViewLogDestination(textView: textView, owner: log, identifier: "com.cerebralgardens.xcglogger.logdestination.textview"))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment