Thanks for the detailed description of what you’re seeing.
Again, I’m going to focus on the iOS 16 side of this, and for good reason. Your description of the iOS 16 behaviour doesn’t match my reality (-: This suggests that something else is going on your project.
Lemme start with my reality! Swift’s Logger
type is just a front end to the system log. This does not log to stdout
or stderr
unless you take unsupported actions to enable that (like setting OS_ACTIVITY_DT_MODE
). You wrote:
Okay, so the following is happening on iOS 16 and works as expected:
…
6. When I run the app from the Home screen, the resulting file
does contain log entries I wrote using Logger
which is clearly at odds with my reality. So, just to be sure, I set up a test for this.
Consider the code pasted in below. It’s a simple implementation of the technique you’ve described. I added this code to an newly created project and:
-
Implemented updateUI()
to update a pair of labels with the counts
-
Added three buttons that call printToStdout()
, printToStderr()
, and logWithLogger()
I used Xcode to build and run this on my iOS test device running 16.7. I then stopped it and ran it again from the Home screen. Finally, I tapped all three buttons. The stdout
and stderr
buttons updated the labels. The Logger
button did not.
I’ve no idea how you’re main app is capturing Logger
output on iOS 16. I suspect that you, or one of the libraries you’re using, is doing something unsupported to enable this.
My advice is that you create a small test app with the code below to verify my results. I expect you’ll see the same results as me. If not, we should talk some more (-:
If you do see the same results as me, you can then compare your test app with your main app to see why they behave differently.
And once you’ve worked out why this is working on iOS 16, we can talk about what you can do on iOS 17!
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
var pipeStdoutQ: Pipe? = nil
var pipeStderrQ: Pipe? = nil
func hookStdoutAndStderr() {
func hook(_ fd: FileDescriptor, _ accumulate: @escaping (Int) -> Void) -> Pipe {
let pipe = Pipe()
let write = FileDescriptor(rawValue: pipe.fileHandleForWriting.fileDescriptor)
_ = try! write.duplicate(as: fd)
pipe.fileHandleForReading.readabilityHandler = { fh in
let count = fh.availableData.count
DispatchQueue.main.async {
accumulate(count)
}
}
return pipe
}
self.pipeStdoutQ = hook(.standardOutput, { self.stdoutCount += $0 })
self.pipeStderrQ = hook(.standardError, { self.stderrCount += $0 })
}
var stdoutCount: Int = 0 { didSet {
self.updateUI()
} }
var stderrCount: Int = 0 { didSet {
self.updateUI()
} }
func printToStdout() {
let msg = "stdout says Hello Cruel World! \(Date())\n"
write(STDOUT_FILENO, msg, msg.utf8.count)
}
func printToStderr() {
let msg = "stderr says Goodbye Cruel World! \(Date())\n"
write(STDERR_FILENO, msg, msg.utf8.count)
}
let log = Logger(subsystem: "com.example.apple-samplecode.Test739047", category: "app")
func logWithLogger() {
log.log("Logger says Hello Cruel World! \(Date())")
}