import Foundation protocol Logger { } private let df: DateFormatter = { let df = DateFormatter() df.dateStyle = .short df.timeStyle = .short return df }() func log(_ message: String, file: String = #file, line: Int = #line) { let date = df.string(from: Date()) let m = "[\(date)][\(file.components(separatedBy: "/").last ?? file):\(line)] \(message)" print(m) Log.write(m + "\n") } extension Logger { static var logToken: String { "[" + String(describing: self) + "] " } func error(_ message: String) { Self.addToFile(Self.logToken + "ERROR: " + message) } func log(_ message: String) { Self.addToFile(Self.logToken + message) } static func error(_ message: String) { addToFile(logToken + "ERROR: " + message) } static func log(_ message: String) { addToFile(logToken + message) } private static func addToFile(_ message: String) { Log.write("\n" + message) print(message) } } enum Log { static func set(logFile: String) throws { let url = URL(fileURLWithPath: logFile) if !FileManager.default.fileExists(atPath: logFile) { try "Log started".write(to: url, atomically: false, encoding: .utf8) } file = FileHandle(forWritingAtPath: logFile) } static func write(_ message: String) { guard let f = file else { return } f.write(message.data(using: .utf8)!) } private static var file: FileHandle? }