为什么可观察对象中的update变量不更新视图?

我是SwiftUI的新手。学习新属性,例如@ State,@ Binding,@ EnvironmentObject等。

我当前正在使用登录模板,在可观察对象中定义一个绑定@Published变量,该变量允许在登录页面和主页之间进行切换。但是,当我更新可观察对象内部的变量时,主页不会显示。它仍然在登录页面中。我的代码中缺少什么?


struct ContentView: View {

    @EnvironmentObject var loginViewModel: LoginViewModel



    var body: some View {

        return Group {
            if loginViewModel.signInSuccess {
                MainPageView()
            }
            else {
                LoginView(signInSuccess: $loginViewModel.signInSuccess).environmentObject(LoginViewModel())
            }
        }


    }


}



final class LoginViewModel: ObservableObject  {
      @Published var signInSuccess:Bool = false;

      func performLogin() {
           signInSuccess = true;
      }

}


struct LoginView: View {

    @EnvironmentObject var loginViewModel: LoginViewModel

    @Binding var signInSuccess: Bool;

    var body: some View {

        Button(action: submit) {
                Text("Login")
                    .foregroundColor(Color.white)

        }

    }

    func submit() {
        loginViewModel.performLogin()
        // signInSuccess = true;
    }


}

如果我尝试在loginView中更新绑定'signInSuccess',它可以成功将视图更新为mainView。但是,有什么方法可以更新Observable Object中的signInSuccess,同时也可以将ContentView更新为MainView吗?

jinjin1991 回答:为什么可观察对象中的update变量不更新视图?

是的,您只需按以下方式更改视图代码。 绑定实际上是不必要的。

struct ContentView: View {

@EnvironmentObject var loginViewModel: LoginViewModel 

var body: some View {

    return Group {
        if loginViewModel.signInSuccess {
           MainPageView()()
        }
        else {
            LoginView(signInSuccess: $loginViewModel.signInSuccess).environmentObject(self.loginViewModel)
        }
    }


}


}


   window.rootViewController = UIHostingController(rootView:    ContentView().environmentObject(LoginViewModel())
,

如果要使用环境变量,则必须在SceneDelegate中声明它,并在ContontentView上进行设置:

class SceneDelegate: UIResponder,UIWindowSceneDelegate {

    var window: UIWindow?

    var loginViewModel = LoginViewModel()

    func scene(_ scene: UIScene,willConnectTo session: UISceneSession,options connectionOptions: UIScene.ConnectionOptions) {


        let contentView = ContentView()
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = HostingViewController(rootView: contentView.environmentObject(loginViewModel))
            self.window = window
            window.makeKeyAndVisible()
        }
    }
    // etc.

然后在您的ContenView中,您不需要在LoginView上以任何方式对其进行设置,因为它是由环境保存的:

struct ContentView: View {

    @EnvironmentObject var loginViewModel: LoginViewModel

    var body: some View {

        return Group {
            if loginViewModel.signInSuccess {
                MainPageView()
            } else {
                LoginView()
            }
        }
    }
}

在模型中,请确保将signInSuccess声明为private(set),以便只能在类内进行设置,并且只能从其他位置进行读取:

final class LoginViewModel: ObservableObject  {
      @Published private(set) var signInSuccess:Bool = false;

      func performLogin() {
           signInSuccess = true;
      }

}

最后,在LoginView中,您只需要包含@EnvironmentObject,其他所有内容都将起作用。

struct LoginView: View {

    @EnvironmentObject var loginViewModel: LoginViewModel

    var body: some View {
        Button(action: { self.loginViewModel.performLogin() }) {
                Text("Login")
                    .foregroundColor(Color.white)
        }

    }
}
本文链接:https://www.f2er.com/3156794.html

大家都在问