import Foundation import SwiftUI import os.log import Combine /// 日志级别枚举 enum LogLevel: String, CaseIterable { case debug = "🔍" case info = "ℹ️" case warning = "⚠️" case error = "❌" case success = "✅" var localizedName: String { switch self { case .debug: return "调试" case .info: return "信息" case .warning: return "警告" case .error: return "错误" case .success: return "成功" } } } /// 日志管理器 class Logger: ObservableObject { static let shared = Logger() @Published var isEnabled = true @Published var minimumLevel: LogLevel = .debug private let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "HH:mm:ss" return formatter }() private init() {} /// 记录日志 /// - Parameters: /// - level: 日志级别 /// - message: 日志消息 /// - file: 文件名(自动获取) /// - function: 函数名(自动获取) /// - line: 行号(自动获取) /// - className: 类名(可选) func log( _ level: LogLevel, _ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil ) { guard isEnabled && shouldLog(level) else { return } let timestamp = dateFormatter.string(from: Date()) let fileName = URL(fileURLWithPath: file).lastPathComponent let functionName = function let lineNumber = line let classDisplayName = className ?? "Unknown" let logMessage = "[\(timestamp)] \(level.rawValue) [\(classDisplayName)] [\(fileName):\(lineNumber)] \(functionName): \(message)" // 输出到控制台 print(logMessage) // 同时输出到系统日志(可选) #if DEBUG // os_log("%{public}@", log: .default, type: .debug, logMessage) #endif } /// 检查是否应该记录该级别的日志 private func shouldLog(_ level: LogLevel) -> Bool { let levelOrder: [LogLevel] = [.debug, .info, .warning, .error, .success] guard let currentIndex = levelOrder.firstIndex(of: minimumLevel), let messageIndex = levelOrder.firstIndex(of: level) else { return false } return messageIndex >= currentIndex } // MARK: - 便捷方法 func debug(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { log(.debug, message, file: file, function: function, line: line, className: className) } func info(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { log(.info, message, file: file, function: function, line: line, className: className) } func warning(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { log(.warning, message, file: file, function: function, line: line, className: className) } func error(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { log(.error, message, file: file, function: function, line: line, className: className) } func success(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { log(.success, message, file: file, function: function, line: line, className: className) } } // MARK: - 全局日志函数 /// 全局调试日志函数 func logDebug(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { Logger.shared.debug(message, file: file, function: function, line: line, className: className) } /// 全局信息日志函数 func logInfo(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { Logger.shared.info(message, file: file, function: function, line: line, className: className) } /// 全局警告日志函数 func logWarning(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { Logger.shared.warning(message, file: file, function: function, line: line, className: className) } /// 全局错误日志函数 func logError(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { Logger.shared.error(message, file: file, function: function, line: line, className: className) } /// 全局成功日志函数 func logSuccess(_ message: String, file: String = #file, function: String = #function, line: Int = #line, className: String? = nil) { Logger.shared.success(message, file: file, function: function, line: line, className: className) } // MARK: - 扩展:获取类名 extension NSObject { var className: String { return String(describing: type(of: self)) } static var className: String { return String(describing: self) } } extension View { var className: String { return String(describing: type(of: self)) } }