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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With