6

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

3

4 Answers 4

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)
Sign up to request clarification or add additional context in comments.

4 Comments

it is still not clear to mo how to use it.. Would you like to give me a short example please?
I have added the example
@mattt have recently wrote an article on the topic. Good read nshipster.com/textoutputstream
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???
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)
    }
}

1 Comment

I use "a+", stdout instead of ` "a", stderr` in order to see all log in the txt file.
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)

Comments

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)
        }
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.