Skip to content

Instantly share code, notes, and snippets.

@popmedic
Last active July 13, 2018 15:02
Show Gist options
  • Save popmedic/f26fe97707482dad745a8047c125924c to your computer and use it in GitHub Desktop.
Save popmedic/f26fe97707482dad745a8047c125924c to your computer and use it in GitHub Desktop.
LoggerTextView is a subclass of UITextView that can be used as a log for QA of a project. Uses https://gist.github.com/popmedic/291af6918ac4f0a43d187e2379484c64
import UIKit
let __kDefaultColorError = UIColor.redColor()
let __kDefaultColorSuccess = UIColor.greenColor()
let __kDefaultColor = UIColor.whiteColor()
let __kDefaultColorBackground = UIColor.blackColor()
let __kDefaultFont = UIFont(name: "Menlo-Bold", size: 12.0)!
let __kLoggerTextFieldListenerName = "com.webroot.control.LoggerTextField"
public class Logger {
/// Singleton for logging
public static var shared:Logger = Logger()
/// UIColor to use for logError
public var errorColor = __kDefaultColorError
/// UIColor to use for logSuccess
public var successColor = __kDefaultColorSuccess
/// Private Array of classes that will listen to the logger for events
public var _listeners = [(name:String,listener:LoggerListener)]()
/// Private Array of AttributedStrings, stores all the lines logged (a line is added every time a log function is called.
private var _lines = [NSAttributedString]()
/// Private UIColor used to override the super.textColor values.
private var _color = __kDefaultColor
/// Private UIColor used to override the super.backgroundColor values.
private var _backgroundColor = __kDefaultColorBackground
/// Private UIFont used to override the super.font values.
private var _font = __kDefaultFont
/// clear - Clears the text.
public func clear(){
self._lines.removeAll()
}
/// refresh - Refreshes the text
public func refresh(){
let oldLines = self._lines
self.clear()
for line in oldLines {
self.log(Attributed:line, logToDBGLog: false)
}
}
/// addListener - Adds a LoggerListener with name name
public func addListener(listener:LoggerListener, name: String) {
self._listeners.append((name:name, listener:listener))
}
/// removeListener - Removes a LoggerListener with name name
public func removeListener(name:String) {
for (index, value) in self._listeners.enumerate() {
if value.name == name {
self._listeners.removeAtIndex(index)
}
}
}
/**
log - log a message to the view.
- Note: This function will advance and add a endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
- color: forground color for message
- backgroundColor: background color for message (to end of string NOT end of line).
- font: font to use for the message
*/
public func log(message:String, color:UIColor = __kDefaultColor, backgroundColor:UIColor = __kDefaultColorBackground, font:UIFont = __kDefaultFont) {
self.log(Attributed:NSAttributedString(string: message, attributes: [
NSFontAttributeName:font,
NSForegroundColorAttributeName:color,
NSBackgroundColorAttributeName:backgroundColor
]))
}
/**
log - Adds a message.
- Note: This function will advance and add a endline to the string. Formatting is only on the current string NOT the line.
- Parameters:
- Attributed attributedMessage: NSAttributedString to be logged
- logToDBGLog: Bool, when true will call NSLog (or equevilent)
*/
public func log(Attributed attributedMessage:NSAttributedString, logToDBGLog:Bool = true){
self._lines.append(attributedMessage)
for value in self._listeners {
value.listener.loggedLine(attributedMessage)
}
if logToDBGLog {
Logger.xcdbgFriendly(attributedMessage.string)
}
}
/**
logSuccess - log a message to the view using the successColor UIColor for textColor/tintColor.
- Note - This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
*/
public func logSuccess(message:String) {
self.log(message, color: self.successColor)
}
/**
logError - log a message to the view using the errorColor UIColor for textColor/tintColor.
- Note - This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
*/
public func logError(message:String) {
self.log(message, color: self.errorColor)
}
/**
xclog - This function will log to the NSLog regardless of it being a debug configuration.
- Parameters:
- object: object to log to log.
- filename: (optional, default to current file name) file to add to the string as where the log function was called from
- line: (optional, defaults to current line) line in filename that the log function was called from
- funcname: (optional, defaults to current function) name of function at line of filename that the log function was called from
*/
public static func xclog<T>(object: T, filename: String = #file, line: Int = #line, funcname: String = #function) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy HH:mm:ss:SSS"
let process = NSProcessInfo.processInfo()
var threadId = "\(NSThread.currentThread())"
threadId = threadId.substringWithRange(threadId.startIndex.advancedBy(13)..<threadId.startIndex.advancedBy(22)) //.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<")).stringByReplacingOccurrencesOfString("NSThread: 0x", withString: "")
print("\(dateFormatter.stringFromDate(NSDate())) \(process.processName)[\(process.processIdentifier):\(threadId)] \((filename as NSString).lastPathComponent)(\(line)) \(funcname):\r\(object)")
}
public static func xclogFriendly<T>(object:T) {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy HH:mm:ss:SSS"
let process = NSProcessInfo.processInfo()
var threadId = "\(NSThread.currentThread())"
threadId = threadId.substringWithRange(threadId.startIndex.advancedBy(13)..<threadId.startIndex.advancedBy(22)) //.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<")).stringByReplacingOccurrencesOfString("NSThread: 0x", withString: "")
print("\(dateFormatter.stringFromDate(NSDate())) \(process.processName)[\(process.processIdentifier):\(threadId)] \(object)")
}
/**
dbg - This function will log to the NSLog only if it is a debug configuration.
- Parameters:
- object: object to log to log.
- filename: (optional, default to current file name) file to add to the string as where the log function was called from
- line: (optional, defaults to current line) line in filename that the log function was called from
- funcname: (optional, defaults to current function) name of function at line of filename that the log function was called from
*/
public static func xcdbg<T>(object: T, filename: String = #file, line: Int = #line, funcname: String = #function){
#if DEBUG
xclog(object, filename: filename, line: line, funcname: funcname)
#else
#endif
}
public static func xcdbgFriendly<T>(object: T){
#if DEBUG
xclogFriendly(object)
#else
#endif
}
}
public protocol LoggerListener {
func loggedLine(line:NSAttributedString)
}
public class LoggerTextView: UITextView, LoggerListener {
/// UIColor to use for logError
public var errorColor = __kDefaultColorError
/// UIColor to use for logSuccess
public var successColor = __kDefaultColorSuccess
/// Bool: when true every log has a line number (NOTE: based on logs NOT newlines/charage returns.)
public var showLineNumbers:Bool {
get{
return _showLineNumbers
}
set(value) {
if value != _showLineNumbers {
_showLineNumbers = value
refresh()
}
}
}
/// Private UIColor used to override the super.textColor values.
private var _color = __kDefaultColor
/// Private UIColor used to override the super.backgroundColor values.
private var _backgroundColor = __kDefaultColorBackground
/// Private UIFont used to override the super.font values.
private var _font = __kDefaultFont
/// Private Bool used for the showLineNumbers property.
private var _showLineNumbers = false
/// Public UIColor property for the default background color.
override public var backgroundColor: UIColor? {
get {
return self._backgroundColor
}
set(value) {
if let val = value {
self._backgroundColor = val
}
}
}
/// Public UIColor property for the default textColor color.
override public var textColor: UIColor? {
get {
return self._color
}
set(value) {
if let val = value {
self._color = val
}
}
}
/// Public UIColor property for the default tintColor color.
override public var tintColor: UIColor? {
get {
return self._color
}
set(value) {
if let val = value {
self._color = val
}
}
}
/// Public UIFont property for the default font font.
override public var font: UIFont? {
get {
return self._font
}
set(value) {
if let val = value {
self._font = val
}
}
}
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
self._initialize()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self._initialize()
}
/// Private function for common initialization
private func _initialize(){
self.editable = false
self.selectable = true
self.scrollEnabled = true
if self.font == nil {
self.font = __kDefaultFont
}
if self.backgroundColor == nil {
self.backgroundColor = __kDefaultColorBackground
}
if self.textColor == nil {
self.textColor = __kDefaultColor
}
if self.tintColor == nil {
self.tintColor = __kDefaultColor
}
Logger.shared.addListener(self, name: __kLoggerTextFieldListenerName)
}
/// clear - Clears the text.
public func clear(){
self.text = ""
Logger.shared.clear()
}
/// refresh - Refreshes the text
public func refresh(){
let oldLines = Logger.shared._lines
self.clear()
for line in oldLines {
self.log(Attributed:line, logToDBGLog: false)
}
}
/**
log - log a message to the view.
- Note: This function will advance and add a endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
- color: forground color for message
- backgroundColor: background color for message (to end of string NOT end of line).
- font: font to use for the message
*/
public func log(message:String, color:UIColor, backgroundColor:UIColor, font:UIFont) {
self.log(Attributed:NSAttributedString(string: message, attributes: [
NSFontAttributeName:font,
NSForegroundColorAttributeName:color,
NSBackgroundColorAttributeName:backgroundColor
]))
}
/**
log - log a message to the view.
- Note: This function will advance and add a endline to the string. Formatting is only on the current string NOT the line.
- Parameters:
- Attributed attributedMessage: NSAttributedString to be logged
- logToDBGLog: Bool when true will print to xcode log.
*/
public func log(Attributed attributedMessage:NSAttributedString, logToDBGLog:Bool = true){
Logger.shared.log(Attributed: attributedMessage, logToDBGLog: logToDBGLog)
}
/**
log - log a message to the view.
- Note: This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
*/
public func log(message:String) {
if let color = self.textColor {
self.log(message, color: color)
}
else {
self.log(message, color: __kDefaultColor)
}
}
/**
log - log a message to the view.
- Note: This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
- color: forground color for message
*/
public func log(message:String, color:UIColor) {
if let backgroundColor = self.backgroundColor {
self.log(message, color: color, backgroundColor: backgroundColor)
}
else {
self.log(message, color: color, backgroundColor:__kDefaultColorBackground)
}
}
/**
log - log a message to the view.
- Note: This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
- color: forground color for message
- backgroundColor: background color for message (to end of string NOT end of line).
*/
public func log(message:String, color:UIColor, backgroundColor:UIColor) {
if let font = self.font {
self.log(message, color: color, backgroundColor: backgroundColor, font: font)
}
else {
self.log(message, color: color, backgroundColor: backgroundColor, font: __kDefaultFont)
}
}
/**
logSuccess - log a message to the view using the successColor UIColor for textColor/tintColor.
- Note - This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
*/
public func logSuccess(message:String) {
self.log(message, color: self.successColor)
}
/**
logError - log a message to the view using the errorColor UIColor for textColor/tintColor.
- Note - This function will advance add and an endline to the string. Formatting is only on the current string.
- Parameters:
- message: string to be logged
*/
public func logError(message:String) {
self.log(message, color: self.errorColor)
}
public func loggedLine(line: NSAttributedString) {
let mutableTextAttributedString = NSMutableAttributedString(attributedString: self.attributedText)
if self.showLineNumbers {
mutableTextAttributedString.appendAttributedString(NSAttributedString(string: "\(Logger.shared._lines.count):\t", attributes: [
NSFontAttributeName:self._font,
NSForegroundColorAttributeName:self._color,
NSBackgroundColorAttributeName:self._backgroundColor
]))
}
mutableTextAttributedString.appendAttributedString(line)
mutableTextAttributedString.appendAttributedString(NSAttributedString(string: "\n", attributes: [
NSFontAttributeName:self._font,
NSForegroundColorAttributeName:self._color,
NSBackgroundColorAttributeName:self._backgroundColor
]))
self.attributedText = mutableTextAttributedString
self.scrollRangeToVisible(NSRange(location: self.attributedText.length-1, length: 1))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment