IOS日志重定向导出文件

 在写代码的时候我们通常会埋很多的日志,以方便我们在debug的时候查看哪里出的问题。但在控制台打一堆的日志,看起日志的时候总是不方便。 所以我写的一个可以将我们需要的日志单独导出来的类。好用的话记得点赞哦!


import Cocoa

typealias MLog = MTLogHelper

public enum OutputMode: Int {

    case none            =0

    case redirect

    case file

    case console

    case fileAndConsole

}

public class MTLogHelper: NSObject {

    /// Whether to output log files

    public static var outModel: OutputMode = .file

    

    private static var pipe = Pipe()

    private static var once: Bool = true

    private static var lock = NSLock.init()

    private static var semaphore = DispatchSemaphore.init(value: 0)

    private static var redirectQueue = DispatchQueue.init(label: "com.meitu.logRedirected")

    private static var writeQueue = DispatchQueue.init(label: "com.meitu.logWrite")

}

//MARK: - OutPut Model

//MARK: -

extension MTLogHelper {

    //封装的日志输出功能(T表示不指定日志信息参数类型)

    public class func output(_ message:T, file:String = #file, function:String = #function, line:Int = #line) {

#if DEBUG

        let splitLine = "============================================"

        let fileName = (file as NSString).lastPathComponent.replacingOccurrences(of: ".swift", with: "")

        let outPutContent = "\(fileName):\(String(format: "%04d", line)) | \(function) | \(message)"

        

        /// redirect

        if outModel == .redirect {

            redirectQueue.sync {

                if self.once {

                    print("===>LogPath: \(logURL.path)")

                    appendText(splitLine +  splitLine )

                    openConsolePipe()

                    self.once = false

                }

                print(outPutContent)

                semaphore.wait()

            }

            return

        }

        /// one new start

        if self.once {

            self.once = false

            print("===>LogPath: \(logURL.path)")

            //try? FileManager.default.removeItem(at: logURL)

            appendText(splitLine +  splitLine )

        }

        /// output console

        if outModel == .console {

            print("\(timeData)  \(message)")

        }

        /// output file

        if outModel == .file {

            appendText(outPutContent)

        }

        /// output console and file

        if outModel == .fileAndConsole {

            print("\(timeData)  \(message)")

            appendText(outPutContent)

        }

#endif

    }

    

    /// 重定向

    class func openConsolePipe() {

        dup2(pipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO)

        // listening on the readabilityHandler

        pipe.fileHandleForReading.readabilityHandler = { handle in

            let data = handle.availableData

            var str = String(data: data, encoding: .ascii) ?? "No finde console data"

            str = str.replacingOccurrences(of:"\n", with: "")

            appendText(str)

            semaphore.signal()

        }

    }

}

//MARK: - File Path

//MARK: -

extension MTLogHelper {

    /// 输出路径

    private static var logURL: URL {

        let cachePath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]

        return cachePath.appendingPathComponent("console.log")

    }

    

    /// 获取时间

    static var timeData: String {

        let dformatter = DateFormatter()

        dformatter.dateFormat ="yy-MM-dd HH:mm:ss:SS"

        let datestr = dformatter.string(from: Date())

        return datestr

    }

    

    // 输出到指定文件

    class func appendText(_ string: String) {

         try? writeQueue.sync {

            lock.lock()

            //如果文件不存在则新建一个

            if !FileManager.default.fileExists(atPath: logURL.path) {

                FileManager.default.createFile(atPath: logURL.path, contents: nil)

            }

            let fileHandle = try FileHandle(forWritingTo: logURL)

            let stringToWrite = timeData + "  " + string + "\n"

            /// 读取数据再写入

            //let oldData = try String(contentsOf: logURL, encoding: .utf8).data(using: .utf8)!

            let data = stringToWrite.data(using: .utf8)!

            //data.append(oldData)

            if #available(macOS 10.15.4, *) {

                try fileHandle.seekToEnd()

            }else {

            }

            fileHandle.write(data)

            lock.unlock()

        }

    }

}


使用方法:

  MTLogHelper.MTLog("xxxxxx")

需要查看日志的时候可以设置

MTLogHelper.outModel = .file 

可以选择日志是单独显示在console.log 内, 或直接打印在控制台。 需要打印一份完整日志时,可以设为.redirect 得到一份完整的日志

如果使用的模块比较多所以我们可以在MTLog基础上封装了一些枚举。在我需要的时候可以针对不同模块过滤导出日志。

当日志导入文件时会在控制台内打印保存路径!

(未允许不可转载)

你可能感兴趣的:(IOS日志重定向导出文件)