Home > Mobile >  Why is SwiftUI not setting a state variable from decoded JSON?
Why is SwiftUI not setting a state variable from decoded JSON?

Time:09-29

I am trying to download a JSON list of first names and use them to randomly pick a name. However when I step through in the debugger I see that self.names is not being set to the parsed JSON. Why is this?

struct ContentView: View {

  @State var names:[String] = []
  init(){
      getNames()
  }
  var body: some View {
      List {displays person objects from coredata}
      Button(action: addItem)
  }

  func getNames(){
    // URL & JSON setup
    session.dataTask(with: request) { data, response, error in
        guard error == nil else {return}
        do {
            let decoder = JSONDecoder()
            let decodedNames = try decoder.decode([String].self, from: data!)
            DispatchQueue.main.async {
                self.names = decodedNames // self.names not being set here
            }
        }
        catch {}
    }.resume()
  }
  
  func addItem() {
      let p = Person(context: viewContext)
      p.age = String(Int.random(in: 1...100))
      p.name = self.names[Int.random(in: 0..<self.names.count)] // crashes here
      try! viewContext.save()
  }
  

CodePudding user response:

Views in SwiftUI do not have a guaranteed lifespan. They're transitive by nature and the system can rebuild them at any time. If you have an asynchronous method in a View, there is no guarantee that this same instance of the View will exist in the hierarchy by the time it returns.

For this reason, it's generally recommended that you move asynchronous code to a view model (ObservableObject with a @Published property). The ObservableObject will have a guaranteed lifespan and can communicate the data back to the view via the @Published property.

  • Related