为啥可观察对象中的更新变量不会更新视图?
Posted
技术标签:
【中文标题】为啥可观察对象中的更新变量不会更新视图?【英文标题】:Why update variable in observable object does not update the view?为什么可观察对象中的更新变量不会更新视图? 【发布时间】:2019-11-05 19:51:03 【问题描述】:我是 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 对象中的 signInSuccess,同时将 ContentView 更新为 MainView?
【问题讨论】:
【参考方案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())
【讨论】:
感谢您的正确建议。我对 environmentObject 有了更好的了解。【参考方案2】:如果你想使用环境变量,你必须在你的 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)
【讨论】:
以上是关于为啥可观察对象中的更新变量不会更新视图?的主要内容,如果未能解决你的问题,请参考以下文章