Igor Samtsevich
Igor Samtsevich

Reputation: 419

How to force view update onAppear in swift ui

Is it possible to view content view onAppear? The method is called, but list does not updated Seems it should be some way to do this

import SwiftUI

var texts = ["0", "0", "0"]

struct ContentView: View {


  var body: some View {
      List {
        Text(texts[0])
        Text(texts[1])
        Text(texts[2])

      }
      .onAppear(){
        texts[0] = "1"
        print(texts)
    }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Upvotes: 6

Views: 11680

Answers (2)

Andrew
Andrew

Reputation: 28539

If you want to cause a re-render you need to use state.

If you bring the texts variable inside the ContentView struct and declare it as @State then it will cause the ContentView to re-render.

Note you will have to use self in the onAppear as you are referencing texts in a closure.

struct ContentView: View {

  @State private var texts = ["0", "0", "0"] . // Apple suggests that these should be private

  var body: some View {
      List {
        Text(texts[0])
        Text(texts[1])
        Text(texts[2])

      }
      .onAppear(){
        self.texts[0] = "1"
        print(self.texts)
      }
    }
}

If however you are wanting to share the texts across multiple views then you will need create an environment object. You can do this as follows:

Create an ObservableObject.

class Texts: ObservableObject {
    @Published var texts = ["0", "0", "0"] // You can obviously choose whichever name you want for this variable.
}

Then in your SceneDelegate create an instance of this object and attach it to your ContentView.

let texts = Texts()
let contentView = ContentView().environmentObject(texts)

Then in ContentView.swift you can use it like this:

struct ContentView: View {

  @EnvironmentObject var texts: Texts

  var body: some View {
      List {
        // notice that you have to access the texts array that is stored in texts object
        Text(texts.texts[0])
        Text(texts.texts[1])
        Text(texts.texts[2])

      }
      .onAppear(){
        self.texts.texts[0] = "1"
        print(self.texts.texts)
       }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(Texts())
    }
}

Upvotes: 5

Sorin Lica
Sorin Lica

Reputation: 7636

"texts" should be @State if you want the view to update when the variable changes and place it inside the view

  @State var texts = ["0", "0", "0"]

Upvotes: 0

Related Questions