iOS Swift: write print and debug prints into a file
Asked Answered
M

4

7

Evening, is it possible to save in a file all the prints and the debug prints?

I would like to have the logs of what my application does even when is not launched from Xcode.

I was thinking to override the print and the debugPrint methods and to write the input into a file.

Thanks

Meagher answered 20/11, 2018 at 12:5 Comment(2)
Possible helpful: #41924468, #41680504Morphosis
check https://mcmap.net/q/10131/-how-to-nslog-into-a-fileSeptember
K
6

There are methods in Swift Standard Library:

func print<Target>(_ items: Any..., separator: String = default, terminator: String = default, to output: inout Target) where Target : TextOutputStream

and

func debugPrint<Target>(_ items: Any..., separator: String = default, terminator: String = default, to output: inout Target) where Target : TextOutputStream

You can create an object that implements TextOutputStream that will save a message to a file of your choice. This is very useful if you already have existing prints in the codebase. You can then just add the additional parameter to them. Remember that those prints will then stop logging to the standard output (console).

Documentation for print

Documentation for debugPrint

Example:

final class LogDestination: TextOutputStream {
  private let path: String
  init() {
    let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    path = paths.first! + "/log"
  }

  func write(_ string: String) {
    if let data = string.data(using: .utf8), let fileHandle = FileHandle(forWritingAtPath: path) {
      defer {
        fileHandle.closeFile()
      }
      fileHandle.seekToEndOfFile()
      fileHandle.write(data)
    }
  }
}

And then

// I would probably use Singleton for this
var dest = LogDestination()
print("My test message", to: &dest)
Kilt answered 20/11, 2018 at 12:24 Comment(4)
it is still not clear to mo how to use it.. Would you like to give me a short example please?Meagher
I have added the exampleDescent
@mattt have recently wrote an article on the topic. Good read nshipster.com/textoutputstreamDescent
I guess, this does not work in xcode 12.4. I love Apple technologies. However, I would would really appreciate if they could stop making changes to swift. Apple??? Hello???Yolande
R
2

Its possible to write all print/debugPrint logs to file in iOS. Use below for writing debug logs to files.

Note: If you are using the below code logs will not print on console.

func writeIntoFile() {
    if let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
        let filePath = documentDirectoryPath + "/logfile.txt"
        freopen(filePath.cString(using: .ascii), "a", stderr)
    }
}
Rondarondeau answered 20/11, 2018 at 12:16 Comment(1)
I use "a+", stdout instead of ` "a", stderr` in order to see all log in the txt file.Tael
B
2

A more modern version of @Tomasz Bąk proposal:

final class LogDestination: TextOutputStream {
static var dest = LogDestination()

private let logURL: URL
init() {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    logURL = paths.first!.appendingPathComponent("log.txt", conformingTo: .plainText)
}

func write(_ string: String) {
    do {
        if !FileManager.default.fileExists(atPath: logURL.path) {   // does it exits?
            FileManager.default.createFile(atPath: logURL.path, contents: nil)
        }
        if let data = string.data(using: .utf8) {
            let fileHandle = try FileHandle(forWritingTo: logURL)
            try fileHandle.seekToEnd()
            try fileHandle.write(contentsOf: data)
            try fileHandle.close()
        }
    } catch let error as NSError {                              // something wrong
        print("Unable to write log: \(error.debugDescription)") // debug printout
    }
}

}

with usage:

print("Hello World", to: &LogDestination.dest)
Brunhilde answered 20/3, 2024 at 10:31 Comment(0)
F
1

I think you want your logs into an external file. If so, then you can try this:

func redirectLogs(flag:Bool)  {
    if flag {
        if let documentsPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
            let logPath = documentsPathString.appending("app.log")
            freopen(logPath.cString(using: String.Encoding.ascii), "a+",stderr)
        }
    }
}
Farthing answered 20/11, 2018 at 13:40 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.