Home > Blockchain >  How do I pass environment object between sibling views?
How do I pass environment object between sibling views?

Time:09-22

I'm trying to pass some data between sibling views.

I got a VerseDetailView with a button:

@StateObject var favoritesViewModel = FavoritesViewModel()
...
Button("Add to favorite") {
 favoritesViewModel.add(verse: verse)
}

My FavoritesViewModel looks like this:

class FavoritesViewModel: ObservableObject {
    
    @Published var favoriteVerses: [Verse] = []
    
    func add(verse: Verse) {
        favoriteVerses.append(verse)
    }
    
}

How would I pass favoriteVerses to display in a completely different subview?

My main app file looks like this:

var body: some Scene {
        WindowGroup {
            TabView {
                NavigationView {
                    BookView() // VerseDetailView is a child of this view
                }
                .tabItem {
                    Image(systemName: "book")
                    Text("Books")
                       
                }
                NavigationView {
                    FavoritesView() // I want to get the array of favoriteVerses here
                }
                
                .tabItem {
                    Image(systemName: "bookmark")
                    Text("Favorites")
                }
            }
        }
    }

My FavoritesView looks like this:

struct FavoritesView: View {
    @EnvironmentObject var favoritesViewModel: FavoritesViewModel 
     // is this correct?
    // I get a hread 1: "Fatal error: No ObservableObject of type FavoritesViewModel found" error
    
    var body: some View {
        
            List {
                Section(header: Text("Favorite verses")) {
                    ForEach(favoritesViewModel.favoriteVerses) { verse in
                        Text(verse.verse)
                    }
                }
                
            }
    }
    
}

I tried adding this at the top of the main app file:

var favoritesViewModel = FavoritesViewModel()
...
NavigationView { 
  FavoritesView().environmentObject(favoritesViewModel)
}

But that doesn't work either

CodePudding user response:

Add it for common top view (in your case it is TabView), like

TabView {
    NavigationView {
        BookView() // VerseDetailView is a child of this view
    }
    .tabItem {
        Image(systemName: "book")
        Text("Books")
           
    }
    NavigationView {
        FavoritesView() // I want to get the array of favoriteVerses here
    }
    
    .tabItem {
        Image(systemName: "bookmark")
        Text("Favorites")
    }
}
.environmentObject(favoritesViewModel)   // << here !!

CodePudding user response:

You can pass environmentObject to each view like this:

TabView {
NavigationView {
    BookView() // VerseDetailView is a child of this view
}
.tabItem {
    Image(systemName: "book")
    Text("Books")
       
}
.environmentObject(favoritesViewModel)

NavigationView {
    FavoritesView() // I want to get the array of favoriteVerses here
}
.tabItem {
    Image(systemName: "bookmark")
    Text("Favorites")
}
.environmentObject(favoritesViewModel)

}
  • Related