Created
October 1, 2025 14:33
-
-
Save robinkunde/5e0d037f5b80bc95b75cc8db36d5efda to your computer and use it in GitHub Desktop.
redirect_xcode_logs.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #if DEBUG | |
| import Foundation | |
| class DebugLogger { | |
| static let shared: DebugLogger = { | |
| let logger = DebugLogger() | |
| logger.openConsolePipe() | |
| return logger | |
| }() | |
| static private var inputPipe = Pipe() | |
| static private var outputPipe = Pipe() | |
| static private var fileRedirectURL: URL? | |
| private init() { } | |
| func redirectOutputToFile(_ fileURL: URL) { | |
| DebugLogger.fileRedirectURL = fileURL | |
| } | |
| private func openConsolePipe() { | |
| // Route everything that comes in throught the outputPipe back to xcode console | |
| dup2(fileno(stdout), DebugLogger.outputPipe.fileHandleForWriting.fileDescriptor) | |
| // Route printing functions that go to sys pipes (stdout & stderr) into local inputPipe | |
| dup2(DebugLogger.inputPipe.fileHandleForWriting.fileDescriptor, fileno(stdout)) | |
| dup2(DebugLogger.inputPipe.fileHandleForWriting.fileDescriptor, fileno(stderr)) | |
| // Begin notification listener | |
| let inputReadHandler = DebugLogger.inputPipe.fileHandleForReading | |
| NotificationCenter.default.addObserver(self, selector: #selector(handlePipeNotification(notification:)), name: FileHandle.readCompletionNotification, object: inputReadHandler) | |
| inputReadHandler.readInBackgroundAndNotify() | |
| } | |
| @objc private func handlePipeNotification(notification: Notification) { | |
| // Listen for next input | |
| DebugLogger.inputPipe.fileHandleForReading.readInBackgroundAndNotify() | |
| if let data = notification.userInfo?[NSFileHandleNotificationDataItem] as? Data { | |
| // Write data back to output pipe for xcode to display | |
| DebugLogger.outputPipe.fileHandleForWriting.write(data) | |
| // Write to file if applicable | |
| if let fileURL = DebugLogger.fileRedirectURL { | |
| if !FileManager.default.fileExists(atPath: fileURL.path) { | |
| FileManager.default.createFile(atPath: fileURL.path, contents: nil, attributes: nil) | |
| } | |
| do { | |
| let fileHandle = try FileHandle(forWritingTo: fileURL) | |
| fileHandle.seekToEndOfFile() | |
| fileHandle.write(data) | |
| fileHandle.closeFile() | |
| } catch { /* pass */ } | |
| } | |
| } | |
| } | |
| } | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment