iOSDeveloper131313
iOSDeveloper131313

Reputation: 81

Call a method from a completion variable in a struct with SwiftUI

I am working with SwiftUI. I have a global variable of a viewModel that has a completion. I am trying to find a way to call a method in this class to perfume an action.

struct ContentView: View {

let viewModel = TimerViewModel(totalTime: 15, finished: {
    print("I need it to call a method here")
})

I have tried having it optional then setting it in init but still get this error:

Escaping closure captures mutating 'self' parameter

I hope you can help.

Upvotes: 1

Views: 768

Answers (2)

Asperi
Asperi

Reputation: 257749

Here is possible approach.

struct ContentView: View {
    var viewModel: TimerViewModel? = nil   // needs to be initialized

    init() {
        // assign function directly instead of via capturing closure
        viewModel = TimerViewModel(totalTime: 15, finished: timerCallback)
    }

    var body: some View {
        Text("Demo")
    }

    private func timerCallback() {
        // do anything needed here
    }
}

Upvotes: 1

pawello2222
pawello2222

Reputation: 54516

You get an error because you try to modify the ContentView from inside the TimerViewModel.

An alternative to calling a completion method can be to create a @Published property in the TimerViewModel:

class TimerViewModel: ObservableObject {
    @Published var finished = false // it can be Bool or anything you want to pass to your View

    func end() {
        finished = true
    }
}

And capture its change in the View:

struct ContentView: View {
    @ObservedObject var viewModel = TimerViewModel()
    
    var body: some View {
        VStack {
            Text("Text")
        }
        .onReceive(viewModel.$finished) { finished in
            if finished {
                // timer has finished, you can call some method now
            }
        }
    }
}

Upvotes: 3

Related Questions