I am listening to voiceover changes through NSWorkspace
KVO and here is my code
public final class MyContext: ObservableObject {
public weak var actionHandler: ActionHandler?
public weak var dataProvider: DataProvider?
@Published public private(set) var isVoiceoverEnabled: Bool
@objc private var voiceOverObserver: NSKeyValueObservation?
public init(
actionHandler: ActionHandler,
dataProvider: DataProvider
) {
self.actionHandler = actionHandler
self.dataProvider = dataProvider
self.isVoiceoverEnabled = NSWorkspace.shared.isVoiceOverEnabled
self.voiceOverObserver = NSWorkspace.shared.observe(\.isVoiceOverEnabled) { [weak self] _, _ in
self?.updateVoiceOverState()
}
}
@objc
private func updateVoiceOverState() {
if isVoiceoverEnabled != NSWorkspace.shared.isVoiceOverEnabled {
isVoiceoverEnabled = NSWorkspace.shared.isVoiceOverEnabled
}
}
}
I am in the process of migrating the app to Swift 6 and I am having some trouble fixing the issues in this class.
The compiler complains that the class is not Sendable
Swift 6 concurrency requires that everyhing needs to be isolated to an actor or sendable across different contexts (please correct me if I am wrong)
So, this error is telling me that the callback block can be called from any context and I either have to isolate it to MainActor
or make the class Sendable
.
I tried to make the class Sendable
but ran into issues since I have weak var
s defined.
When I try to isolate the class to MainActor
I run into a different issue
What am I missing here? How do I fix this?
I am trying to learn Swift concurrency in this process and any help here would be very much appreciated!
Making the whole class bounds to any global actors is an approach, for example @MainActor
:
@MainActor
public final class MyContext: ObservableObject {
public init(...) {
...
self.voiceOverObserver = NSWorkspace.shared.observe(\.isVoiceOverEnabled) { [weak self] _, _ in
Task { @MainActor in
self?.updateVoiceOverState()
}
}
}
}