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!
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!
Share Improve this question asked Mar 12 at 22:06 rottweilerrottweiler 1,2231 gold badge12 silver badges23 bronze badges1 Answer
Reset to default 1Making 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()
}
}
}
}