I think this is a possible bug in MainActor, but I can't tell for sure. I have a class marked @MainActor that executes a method in not the Main Thread. However, I have read that actors only work when you play properly with them. Maybe I've broken one of the rules.
Here is a mini example that will run in a Playground:
import UIKit
@MainActor class MiyagiDo {
func block() {
print("block \(Thread.current)")
}
}
class CobraKai:NSObject, UIApplicationDelegate {
func kick(_ other:MiyagiDo) async throws {
print("kick \(Thread.current)")
try await Task.sleep(nanoseconds:1000000000)
print("After kick \(Thread.current)")
other.block()
}
}
Task {
let sam = await MiyagiDo()
let robbie = CobraKai()
try await robbie.kick(sam)
}
When you run this, the output looks like:
kick <NSThread: 0x6000018b4740>{number = 5, name = (null)}
After kick <NSThread: 0x6000018b0600>{number = 7, name = (null)}
block <NSThread: 0x6000018b0600>{number = 7, name = (null)}
Note that block() is running on thread 7 even though MiyagiDo is marked as @MainActor.
Can someone confirm my suspicions? From what I know, the call to other.block() should require an await, but the compiler does not complain, and if I put in an await, it doesn't work anyway.
Calling other.block() doesn't require await because your class CobraKai is implicitly @MainActor since it conforms to UIApplicationDelegate, which is declared a @MainActor protocol. If you delete that conformance, you will see that the compiler will require you to write await other.block().
However, despite the implicit global actor isolation inferred for CobraKai, the behavior here is different than if you explicitly write @MainActor class CobraKai. I suspect this is some oversight; certainly, it'd be a confusing language rule otherwise.
Only code written in the same file where the protocol conformance is declared implicitly inherits that protocol’s global actor isolation, according to the approved proposal.
Interestingly, if we remove "final" from Presenter declaration, everything works fine. So it seems because of some optimisation main actor isolation is not ensured.