Swift Concurrency in Real Apps
Consider this code, wherein we create a custom
NSTableColumn
that uses an image instead of aString
as its header.
Holly Borla posted a fix that special-cases NSObject.init()
:
Now, overriding
NSObject.init()
within a@MainActor
-isolated type is difficult-to-impossible, especially if you need to call an initializer from an intermediate superclass that is also@MainActor
-isolated. Standard opt-out tools likeMainActor.assumeIsolated
cannot be applied to things like stored property initialization andsuper.init()
, making the issue extremely difficult to work around. This is a major usability regression for programs that interoperate with Objective-C and make heavy use of@MainActor
-isolated types.[…]
I can’t reproduce a failure by overriding
viewDidAppear
in a@MainActor
-isolated subclass ofUIViewController
, but if this is happening for methods that are marked asnonisolated
or otherwise aren’t annotated with@MainActor
, then that is a deliberate result of my original change. Overriding superclass methods and changing isolation does risk a data-race, which is why I made the original change. If you believe the superclass method is incorrectly annotated, that is a framework problem that you should report via Apple Feedback Assistant.
(As it turns out,
UINib
actually isMainActor
-isolated, whileNSNib
is not. There’s one person out there somewhere maintaining a cross-platform app that uses nibs and this is going to make their life hell.)The whole point of Nibs is to serialize UI components. That’s literally the only reason it exists. And that doesn’t work in Swift 6[…]
[…]
The compiler must honor the API contract of
awakeFromNib
. The framework maintainers have decided to not apply any isolation. The types and APIs aren’t able to fully describe the concurrent behavior, but the developer knows what’s actually going to happen at runtime.This is a special-case of a very common issue and is exactly why dynamic isolation exists.
[…]
Some APIs, even really important ones that you use every day, just won’t ever work well with Swift concurrency. I’m certain some language changes could make things a little easier here and there. But, largely, these problematic APIs are going to be deprecated and replaced. It’s happening with Notifications right now.
Pretty sure there are use cases for background threads. I think code for printing uses
NSView
, and usually involves a background op.
TIL:
awakeFromNib()
can be called more than once when objects are loaded from XIBs.IDK, maybe that is something that should be mentioned in the documentation.
Previously:
- SwiftUWhy
- Watch Out for Counterintuitive Implicit Actor-Isolation
- Swift Concurrency Proposal Index
- Problematic Swift Concurrency Patterns
- Swift Concurrency and Objective-C
- Unwanted Swift Concurrency Checking
- Swift 6