Home > Software design >  How I can solve issue with assigning view function to StateObject propety
How I can solve issue with assigning view function to StateObject propety

Time:01-10

I am trying to assign regular function like this

var body: some View {
        contentView
        .task {
                navigation.tabBarVisibility = .hidden
                viewModel.fetchWordset()
                synthesizer.onNextUtteranceEnded = onNextUtteranceEnded
            }
}

private func onNextUtteranceEnded(_ utterance: AVSpeechUtterance) {
        guard utterance.voice?.language == "pl-PL" else { return }
        viewModel.next()
}    

That is defined in swiftui view

To @StateObject var SpeechSynthesizer

that has property

public final class SpeechSynthesizer: NSObject, ObservableObject, AVSpeechSynthesizerDelegate {

    @Published public var isSpeaking = false

    public var onNextUtteranceStarted: ((AVSpeechUtterance) -> Void)?
    public var onNextUtteranceEnded: ((AVSpeechUtterance) -> Void)?

But I am getting warning

Converting function value of type '@MainActor (AVSpeechUtterance) -> ()' to '(AVSpeechUtterance) -> Void' loses global actor 'MainActor'

What I can do about it?

CodePudding user response:

A View is, as you have pointed out, tied to the @MainActor. This means that the implementation of onNextUtteranceEnded in your view is also tied to the main actor.

SpeechSynthesizer's property doesn't hold any such restriction, so the compiler is telling you that it won't be able to help you out should you happen to call onNextUtteranceEnded via the synthesizer from any other actor, you might get yourself in a mess.

The answer is in the warning:

Converting function value of type '@MainActor (AVSpeechUtterance) -> ()'

This is the type of your view's function

to '(AVSpeechUtterance) -> ()' loses global actor 'MainActor'

This is the type of SpeechSynthesizer.onNextUtteranceEnded

You can remove the warning by changing the definition:

public var onNextUtteranceEnded: (@MainActor (AVSpeechUtterance) -> ())?

However, as others have pointed out, this does feel like a strange way to do things. You have a state object, that should be making logic decisions internally and updating published properties. The view should just be responding to those changes.

  • Related