Hi all,
I'm rewring my app with new async/await keywords, I found a really strange behavior when "guard let" and "if let" statement is used in an asynchronous context, it cause the @MainActor to stop working, see the demo code here:
import Foundation
@MainActor
class MainActorTester {
func failedTest() {
let actor = TestActor()
Task {
// Before guard let await, Thread.isMainThread is "true"
print("Task started ->>> in main thread: \(Thread.isMainThread)")
guard let result = await actor.result else {
// After guard let await, Thread.isMainThread is "false"
print("Task ended ->>> in main thread: \(Thread.isMainThread)")
return
}
}
}
func successTest() {
let actor = TestActor()
Task {
print("Task started ->>> in main thread: \(Thread.isMainThread)")
// Before await, Thread.isMainThread is "true"
let result = await actor.result
guard result != nil else {
// After await, Thread.isMainThread is still "true"
print("Task ended ->>> in main thread: \(Thread.isMainThread)")
return
}
}
}
}
actor TestActor {
var result: Bool? = nil
}
MainActorTester().failedTest()
MainActorTester().successTest()
The success & failed tests is doing exactly same thing(At least in my case...), I expect them both running in Main thread, but the failed test isn't.
in the failed test, I write:
// Before await, we are in main thread
guard let result = await actor.result else {
// Here, we are not longer in the main thread
}
in the successful test, I write:
// Before await, we are in main thread
let result = await actor.result
guard let result = result else {
// Here, we are still in the main thread
}
This strange behavior looks like a bug to me, or maybe I break some rules of async/await and actors?
Envorinments:
XCode 13.2
2020 Macbook pro with M1 chip
macOS Monterey 12.1
I create a demo repo for this too, you can download and test it directly: