1

I'm using swiftUI and combine, I'have some business logic in my VM. Some results have to pop my view in navigation view stack.

I'v used this one in some views to simulate backbutton event :

@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

self.presentationMode.wrappedValue.dismiss()

I tried it in view model but it doesn't work. Any ideas ?

theMouk
  • 595
  • 1
  • 7
  • 21

1 Answers1

9

This is a follow up question that I answered previously.

You can achieve this by implementing your custom Publisher which will use .send() method to allow you to send specific values to the subscriber (in this case, your View). You will use onReceive(_:perform:) method defined on the View protocol of SwiftUI to subscribe to the output stream of the custom Publisher you defined. Inside the perform action closure where you will have the access to the latest emitted value of your publisher, you will do the actual dismissal of your View.

Enough of the theory, you can look at the code, should not be very hard to follow, below:

import Foundation
import Combine

class ViewModel: ObservableObject {
    var viewDismissalModePublisher = PassthroughSubject<Bool, Never>()
    private var shouldPopView = false {
        didSet {
            viewDismissalModePublisher.send(shouldPopView)
        }
    }

    func performBusinessLogic() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.shouldPopView = true
        }
    }
}

And the views are:

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                Text("Hello, World!")
                NavigationLink(destination: DetailView()) {
                    Text("Detail")
                }
            }
            .navigationBarTitle(Text("Home"))
        }
    }
}

struct DetailView: View {
    @ObservedObject var viewModel = ViewModel()
    @Environment(\.presentationMode) private var presentationMode
    var body: some View {
        Text("Detail")
        .navigationBarTitle("Detail", displayMode: .inline)
        .onAppear {
            self.viewModel.performBusinessLogic()
        }
        .onReceive(viewModel.viewDismissalModePublisher) { shouldPop in
            if shouldPop {
                self.presentationMode.wrappedValue.dismiss()
            }
        }
    }
}
nayem
  • 7,285
  • 1
  • 33
  • 51