Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Changes to my model/viewModel are not updating my view

I am creating a sample app in SwiftUI and changes to one of my model’s properties are not causing the view to update which it should. I have already tested that the network call is working as expected and the model is being updated with the new text but it isn’t causing the view to be rebuilt and show the new text. I am passing my viewModel through the App object. The text view always shows "initial value" so What might be happening?

import SwiftUI
import Foundation

class ViewModel: ObservableObject {
  
 @Published var model = Model()
  
  var factText: String {
    return model.factText
    
  }
  
  func getNewFact() {
    model.networkCall()
  }
  
  
}

struct ContentView: View {
  
  @ObservedObject var viewModel: ViewModel
  var body: some View {
    VStack {
      Button("New Fact") {
        viewModel.getNewFact()
        //              print(viewModel.model.factText)
      }
      Text(viewModel.model.factText)
    }
    .padding()
  }
}
class Model {
  
  var factText = "initial value"
  
  func networkCall() {
    
    let headers:HTTPHeaders = ["X-Api-Key": Constants.apiKey]
    
    AF.request(Constants.url, headers: headers)
      .responseDecodable(of: [Response].self) {response in
        
        self.factText = response.value![0].fact

      }

  }
 
}


@main
struct FunFactsWatchApp_Watch_AppApp: App {
    var game = ViewModel()
    var body: some Scene {
        WindowGroup {
          ContentView(viewModel: game)
        }
    }
}

>Solution :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Reference types like classes cannot be @Published because the instance (pointer) doesn’t change when a property is modified (actually they can but this is not needed and beyond the question).

Model must be a struct

struct Model {
    var factText: String // can even be `let`
}

the network call must be in the view model

class ViewModel: ObservableObject {
    
    @Published var model = Model(factText: "")
    
    func networkCall() {
        
        let headers:HTTPHeaders = ["X-Api-Key": Constants.apiKey]
        
        AF.request(Constants.url, headers: headers)
            .responseDecodable(of: [Response].self) {response in
                
                self.model = Model(factText: response.value![0].fact)
            }
    }
}

and you have to create and initialize a @StateObject in ContentView

struct ContentView: View {
    
    @StateObject var viewModel = ViewModel()
    
    var body: some View {
        VStack {
            Button("New Fact") {
                viewModel.networkCall()
            }
            Text(viewModel.model.factText)
        }
        .padding()
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading