简体   繁体   中英

SwiftUI ObservedObject does not updated when new items are added from a different view

I have a view model which handles the loading of new data once the app launches and when a new item is added. I have an issue when it comes to showing new items when are added from a new view, for example, a sheet or even a NavigationLink .

View Model

class GameViewModel: ObservableObject {
    //MARK: - Properties
    @Published var gameCellViewModels = [GameCellViewModel]()
    var game = [GameModel]()
    
    init() {
        loadData()
    }
    
    func loadData() {
        if let retrievedGames = try? Disk.retrieve("games.json", from: .documents, as: [GameModel].self) {
            game = retrievedGames
        }
        
        self.gameCellViewModels = game.map { game in
            GameCellViewModel(game: game)
        }
        print("Load--->",gameCellViewModels.count)
    }
    
    func addNew(game: GameModel){
        self.game.append(game)
        saveData()
        loadData()
    }
    
    private func saveData() {
        do {
            try Disk.save(self.game, to: .documents, as: "games.json")
        }
        catch let error as NSError {
            fatalError("""
                Domain: \(error.domain)
                Code: \(error.code)
                Description: \(error.localizedDescription)
                Failure Reason: \(error.localizedFailureReason ?? "")
                Suggestions: \(error.localizedRecoverySuggestion ?? "")
                """)
        }
    }
}

View to load the ViewModel data, leading add button is able to add and show data but the trailing which opens a new View does not update the view. I have to kill the app to get the new data.

    NavigationView{
        List {
            ForEach(gameList.gameCellViewModels) { gameList in
                CellView(gameCellViewModel: gameList)
            }
        }.navigationBarTitle("Games Played")
            .navigationBarItems(leading: Text("Add").onTapGesture {
                let arr:[Int] = [1,2,3]
                self.gameList.addNew(game: GameModel(game: arr))
                }, trailing: NavigationLink(destination: ContentView()){
                    Text("Play")
            })
    }

Play View sample

@State var test = ""
var body: some View {
    VStack(){
        TextField("Enter value", text: $test)
            .keyboardType(.numberPad)
        
        Button(action: {
            var arr:[Int] = []
            arr.append(Int(self.test)!)
            self.gameList.addNew(game: GameModel(game: arr))
        }) {
            Text("Send")
        }
    }
}

To what I can see the issue seems to be here:

List {
   // Add id: \.self in order to distinguish between items 
   ForEach(gameList.gameCellViewModels, id: \.self) { gameList in                    
      CellView(gameCellViewModel: gameList)                    
   }
}

ForEach needs something to orientate itself on in order to know what elements are already displayed and which are not.

If this did not solve the trick. Please update the code you provided to Create a minimal, Reproducible Example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM