View is not updating while app is running

Hi :-)

I´m looking for some help and advice for my little project. Basically I have a Tabview with 3 Tabs. One of them is a View for Favorites. I managed the selection and the saving of the favorites. However, the View for the Favorites is not updating while the app is running. Just when the app is closed and restarted the View of Favorites gets updated.

The Array of Favorites is marked with @Published, the variable in the Favorites-View is marked as @ObservedObject. I searched a lot and can't find my mistake.

„Expression“ is a Struct with about 10 properties.

Class for the Favorites:

class Favorites: ObservableObject {
  
    @Published var favoriteExpressions: [Expression] = [] {
        didSet {
            print("Favorites changed")
        }
    }
    
   private let saveKey = "FavoriteExpressions"
    
    let defaults = UserDefaults.standard
    
    
    
    init() {
      
        if let data = defaults.data(forKey: saveKey) {
            let decoder = JSONDecoder()
            if let decoderSet = try? decoder.decode([Expression].self, from: data) {
                favoriteExpressions = decoderSet
            }
        }
    }
 
     func contains() -> Bool {
     }
    
        func add() {
        }
        
       func remove() {
       }
       
       func save() {
    defaults.set(try? PropertyListEncoder().encode(favoriteExpressions), forKey: saveKey)
        
        let encoder = JSONEncoder()
        if let encodedSet = try? encoder.encode(favoriteExpressions) {
            defaults.set(encodedSet, forKey: saveKey)
        }
       }
  

View for the Favorites

struct View_Favoriten: View {
    @ObservedObject var favoriten = Favorites()
    var body: some View {      
        ZStack {
            LinearGradient()    
            ScrollView {
            LazyVGrid(columns: columns, alignment: .center, spacing: 10) {          
                ForEach(favoriten.favoriteExpressions.sorted(), id: \.self ) { expression in            
                                VStack{           
                            code for displaying data 
                                }
                                .environmentObject(favoriten)
                            }
                } 
                .padding(20)
            }
            }
            .navigationBarHidden(false)
        }
        .accentColor(.accentColor)    
    }

The TabView:


struct ContentView: View {  
    var body: some View {  
        TabView {      
            View_Thema(expressions: Data)
                .tabItem {
                    Image()
                }            
            View_Favoriten()
                .tabItem {
                    Image()
                }
                .environmentObject(Favorites())
            Info_View()
                .tabItem {
                    Image()
                }             
        }
        .environmentObject(Favorites()) 
    }
}

You may observe that I’m saving the entire Expressions, instead of a key value. Previously i used to do that, but I suspected the calculated property (for getting the Structs related to the key value) maybe prohibiting the update of the View, therefore I’ve saved the entire Struct of Expression in an Array.

Thank you in advance! Cheers, Saxa

Post not yet marked as solved Up vote post of Saxa Down vote post of Saxa
723 views

Replies

I miss something in your code.

You send to the environment:

        .environmentObject(Favorites()) 

But I do not see any @EnvironmentObject var

    @EnvironmentObject var favorites: Favorites

have a look on how to use environmentObjects.

Tutorial here: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views

Thanks for your answer and help. Actually I had the @EnvironmentObject in the past, but it was commented out due to the @ObservedObject. Honestly, I´ve tried too many changes and it was messy. Anyway, I´ve followed the tutorial and changed/cleared the code. However, still I got no update while the app is running, but finally a Errorwarning that says what's wrong:

Error at the ForEach of the Favorites:

Accessing StateObject's object without being installed on a View. This will create a new instance each time.

I´ve searched the web and included the .onAppear-Modifier to the ZStack of View_Favoriten:

.onAppear() { favorites.update() }

This causes an update of the favorites-array (data are loaded again, actually the same like the init() does). Finally the View_Favoriten gets updated each time I´ve open it (from the TabView bar).

Little drawback is, that favorites are not immediately removed within the View_Favoriten when the user dislike them, but they are removed only when View_Favoriten is called again from the TabView bar.