Cannot take a view out and make it work - Swift

Viewed 52

Im trying to follow along in a tutorial and I am having a problem with the action after clicking the button. To debug, I cleaned my code of everything apart from the action itself and it still doesn't work... Could you help? Its probably something simple:

import Foundation

class UserInfo: ObservableObject{
    
    @Published var test = "test"
    
}

And the view:

import SwiftUI
import Firebase

struct ContentView: View {
    @StateObject var userInfo: UserInfo = UserInfo()
    var body: some View {
        
            VStack{
            Text(userInfo.test)
            Button(action: {
                self.userInfo.test = "passed"
            }) {
                Text("Log in")
            }
            .font(.title)
            .padding(5)
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(10)
            .padding(.top, 10)
            }
    }
}

Above code will work fine. But when I try to make new view:

struct NewView: View {
    @StateObject var userInfo: UserInfo = UserInfo()
    var body: some View {
        
            VStack{
            Text("test")
            Button(action: {
                self.userInfo.test = "passed"
            }) {
                Text("Log in")
            }
            .font(.title)
            .padding(5)
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(10)
            .padding(.top, 10)
            }
    }
}

And than I put it into Content View:

struct ContentView: View {
    @StateObject var userInfo: UserInfo = UserInfo()
    var body: some View {
        
    NewView()
    
    }
}

The button stops working... I assume that both of those views conform to the ObservableObject. When it is changed ContentView should update, but nothing happens.

1 Answers

You are creating two unrelated UserInfo objects. When you use @StateObject you are saying that you create and own the object and you'll give that object to other things that need it.

To fix the problem you should only create one UserInfo in ContentView and inject that downhill into NewView

struct NewView: View {
    @ObservedObject var userInfo: UserInfo
    var body: some View {
        VStack{
            Text("\(userInfo.test)")
            Button(action: {
                self.userInfo.test = "passed"
            }) {
                Text("Log in")
            }
        }
    }
}

struct NewView_Previews: PreviewProvider {
    static var previews: some View {
        let userInfo: UserInfo = UserInfo()
        NewView(userInfo: userInfo)
    }
}

and

struct ContentView: View {
    @StateObject var userInfo: UserInfo = UserInfo()
    var body: some View {
        NewView(userInfo: userInfo)
    }
}

Here you give the UserInfo downhill to NewView.

Possibly if you want everything in the hierarchy to have access to UserInfo using @EnvironmentObject would be better but that's another topic.

Related