我是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吗?
答案 0 :(得分:1)
是的,您只需按以下方式更改视图代码。 绑定实际上是不必要的。
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())
答案 1 :(得分:0)
如果要使用环境变量,则必须在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)
}
}
}