I'm updating my code to Swift 6 and encountering the following error when calling a method from awakeFromNib()
:
Call to main actor-isolated instance method 'addContentView()' in a synchronous nonisolated context; this is an error in the Swift 6 language mode
The code below defines a custom UIView
subclass, SegmentedHeaderView
, that loads its view from a nib file. I call addContentView()
in awakeFromNib()
to set up the UI. Here’s my code:
class SegmentedHeaderView: UIView {
@IBOutlet var contentView: UIView?
// Other IBOutlet properties
override func awakeFromNib() {
super.awakeFromNib()
addContentView() // Error occurs here
}
@MainActor
func addContentView() {
guard let view = loadViewFromNib() else { return }
view.frame = self.bounds
self.addSubview(view)
contentView = view
}
func loadViewFromNib() -> UIView? {
let nibName = "SegmentedHeaderView"
let bundle = Bundle(for: type(of: self))
let nib = UINib(nibName: nibName, bundle: bundle)
return nib.instantiate(withOwner: self, options: nil).first as? UIView
}
}
In Swift 6, it seems that awakeFromNib()
is considered a nonisolated context, so calling @MainActor
functions directly from it leads to this error.
Using Task { @MainActor in ... }
: I wrapped addContentView()
in a Task
to ensure it runs on the main actor, but this does break my UI.
override func awakeFromNib() {
super.awakeFromNib()
Task { @MainActor in
addContentView()
}
}
I have also tried to use MainActor.assumeIsolated
, seems like working, but I am not sure whether it is a good solution or not.
override func awakeFromNib() {
super.awakeFromNib()
MainActor.assumeIsolated {
addContentView()
}
}
Using MainActor.assumeIsolated
is good solution because awakeFromNib
is a UI related function so It will be surely run on Main Thread. Don't call addContentView
in Task
because it will run asynchronous