UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: How to pass a value between view models without using a singleton

Forums > SwiftUI

Hi everyone. I am really struggling to understand how to share a value from a viewmodel to another one. I have a SettingsView that sets a value in the SettingsViewModel and I would like that value to be accessible in the DashboardViewModel and DashboardView. How can I do that without using a singleton? Here is my code:

public class SettingsViewModel: ObservableObject {
    @Published var isOn: Bool = false
}
struct SettingsView: View {

    @ObservedObject var viewModel = SettingsViewModel()

    var body: some View {
        VStack{
            List {
                Section(header: Text("Select Values")) {
                    HStack {
                        Toggle("Only PM", isOn: $viewModel.isOn)
                    }
                    HStack {
                        Text(String(viewModel.isOn))
                    }
                }
            }

        }
    }
}
public class DashboardViewModel: ObservableObject {
    var settingsViewModel: SettingsViewModel

    init(settingsViewModel: SettingsViewModel) {
        self.settingsViewModel = settingsViewModel
    }
}
struct DashboardView: View {
    var viewModel = DashboardViewModel(settingsViewModel: SettingsViewModel())

    var body: some View {
        Text(String(viewModel.settingsViewModel.isOn))
    }
}

1      

Add SettingsViewModel to the environment in the first view you want to use it and thereafter its is accessible anywhere!

1      

In your file with @main function make it like so

import SwiftUI

@main
struct DemoProjectApp: App {
    @StateObject var viewModel = SettingsViewModel()
    var body: some Scene {
        WindowGroup {
            ContentView(settingsViewModel: viewModel)

        }
    }
}

SettingsView like below

struct SettingsView: View {

    @ObservedObject var viewModel: SettingsViewModel
    var body: some View {
        VStack{
            List {
                Section(header: Text("Select Values")) {
                    HStack {
                        Toggle("Only PM", isOn: $viewModel.isOn)
                    }
                    HStack {
                        Text(String(viewModel.isOn))
                    }
                }
            }

        }
    }
}

And now you do not need the DashBoardViewModel

Just add the DashBoardView as below and it will change as per change in toggle button

struct DashboardView: View {
    @ObservedObject var settingsViewModel: SettingsViewModel

    var body: some View {
        Text(String(settingsViewModel.isOn))
    }
}

Here like below

struct ContentView: View {
    @ObservedObject var settingsViewModel: SettingsViewModel
    var body: some View {
        SettingsView(viewModel: settingsViewModel)
        DashboardView(settingsViewModel: settingsViewModel)
    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(settingsViewModel: SettingsViewModel())
    }
}

1      

Thank you, this works. It also helped me to understand how to do it if I have, for instance, to modify a value within the DashboardViewModel and display it in the DashboardView. I have to inject it like this:

struct ContentView: View {

    @ObservedObject var settingsViewModel: SettingsViewModel

    var body: some View {
        VStack {
            SettingsView(viewModel: settingsViewModel)
            DashboardView(viewModel: DashboardViewModel(settingsViewModel: settingsViewModel))
        }
    }
}

1      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.