Home > Software design >  Swift MainActor not enforced on subclasses
Swift MainActor not enforced on subclasses

Time:03-10

I tried looking for documentation about this but I can't find any.

As far as I know, if you declare your superclass as @MainActor, any subclass will also be considered as @MainActor. However it seems that in practice this is not the case.

Take a UIViewController as example. This is declared as @MainActor, however:

import UIKit

class VC: UIViewController {
    
    func doSomething() {
        DispatchQueue.global().async {
            self.doSomethingElse()
        }
    }
    
    func doSomethingElse() {
        
        print("is main thread? \(Thread.isMainThread)")
    }
}

let vc = VC()

vc.doSomething()

This code will compile without errors and print is main thread? false

This code:

import UIKit

@MainActor
class VC: UIViewController {
    
    func doSomething() {
        DispatchQueue.global().async {
            self.doSomethingElse()
        }
    }
    
    func doSomethingElse() {
        
        print("is main thread? \(Thread.isMainThread)")
    }
}

let vc = VC()

vc.doSomething()

Will not compile, it will show:

error: MyPlayground.playground:20:4: error: call to main actor-isolated instance method 'doSomething()' in a synchronous nonisolated context
vc.doSomething()
   ^

MyPlayground.playground:6:10: note: calls to instance method 'doSomething()' from outside of its actor context are implicitly asynchronous
    func doSomething() {
         ^

error: MyPlayground.playground:8:18: error: call to main actor-isolated instance method 'doSomethingElse()' in a synchronous nonisolated context
            self.doSomethingElse()
                 ^

MyPlayground.playground:12:10: note: calls to instance method 'doSomethingElse()' from outside of its actor context are implicitly asynchronous
    func doSomethingElse() {
         ^


Isn't the behaviour of the compiler in both cases supposed to be the same?

CodePudding user response:

You are correct, this is a bug. SR-15131 was resolved pretty recently so a fix should be coming in Swift 5.6.

  • Related