在父 swiftui 视图中,我怎么知道内部视图 viewmodel void 方法中的状态何时发生变化?
In parent swiftui view how could I know when a state changes in an inner views viewmodel void method?
给定一个 AuthenticationView swiftui 结构包含一个 UserLoginView。 UserLoginView 有一个 UserLoginViewModel class 用于处理登录按钮操作。
在 AuthenticationView 中,我想知道内部 UserLoginView 中的变量值何时发生变化(如果 tutorialScreenIsShowable 在 AuthenticationView 中为真,NavigationLink 导航到下一张幻灯片)。
struct AuthenticationView: View {
@State private var tutorialScreenIsShowable = false
var body: some View {
NavigationView {
ZStack {
NavigationLink(destination: TutorialView(), isActive: $tutorialScreenIsShowable) {
EmptyView()
}
UserLoginView(tutorialScreenIsShowable: self.$tutorialScreenIsShowable)
}
}
}
}
,
struct UserLoginView: View {
@Binding var tutorialScreenIsShowable: Bool
@ObservedObject var userLoginViewModel = UserLoginViewModel()
var body: some View {
Button(action: {
self.userLoginViewModel.loginButtonAction() // it not works but I need this way
// self.tutorialScreenIsShowable = self.userLoginViewModel.loginButtonActionWithReturn() // it works, but its not good in this case
}) {
Text("Log in")
}
}
}
,
class UserLoginViewModel: NSObject, ObservableObject {
@Published var tutorialScreenIsShowable = false
func loginButtonAction() {
self.tutorialScreenIsShowable = true
}
func loginButtonActionWithReturn() -> Bool {
return true
}
}
据我所知,如果函数有一个可以工作的 return 值,但在这种情况下,有一个委托方法 运行 我可以在其中处理变量。
我想尽可能避免@EnvironmentObject,我希望有另一个解决方案。
你能帮我解决这个问题吗?
编辑:我简化了示例。并在此处上传示例项目:https://www.dropbox.com/s/paosp6iom9oks9p/InnerViewPropBind.zip
此行为的起源是 NavigationView
在更新期间多次重新创建自己的内容。
这是一个可能的解决方案 - 一些重新设计和所有权变更。
测试 Xcode 11.4 / iOS 13.4
struct AuthenticationView: View {
// keep model here to avoid recreation inside navigation view
@ObservedObject var userLoginViewModel = UserLoginViewModel()
var body: some View {
NavigationView {
ZStack {
// use binding directly in view model
NavigationLink(destination: Text("TutorialView"), isActive: $userLoginViewModel.tutorialScreenIsShowable) {
EmptyView()
}
UserLoginView(userLoginViewModel: userLoginViewModel)
}
}
}
}
struct UserLoginView: View {
@ObservedObject var userLoginViewModel: UserLoginViewModel
var body: some View {
Button(action: {
self.userLoginViewModel.loginButtonAction()
}) {
Text("Log in")
}
}
}
class UserLoginViewModel: NSObject, ObservableObject {
@Published var tutorialScreenIsShowable = false
func loginButtonAction() {
self.tutorialScreenIsShowable = true
}
func loginButtonActionWithReturn() -> Bool {
return true
}
}
给定一个 AuthenticationView swiftui 结构包含一个 UserLoginView。 UserLoginView 有一个 UserLoginViewModel class 用于处理登录按钮操作。
在 AuthenticationView 中,我想知道内部 UserLoginView 中的变量值何时发生变化(如果 tutorialScreenIsShowable 在 AuthenticationView 中为真,NavigationLink 导航到下一张幻灯片)。
struct AuthenticationView: View {
@State private var tutorialScreenIsShowable = false
var body: some View {
NavigationView {
ZStack {
NavigationLink(destination: TutorialView(), isActive: $tutorialScreenIsShowable) {
EmptyView()
}
UserLoginView(tutorialScreenIsShowable: self.$tutorialScreenIsShowable)
}
}
}
}
,
struct UserLoginView: View {
@Binding var tutorialScreenIsShowable: Bool
@ObservedObject var userLoginViewModel = UserLoginViewModel()
var body: some View {
Button(action: {
self.userLoginViewModel.loginButtonAction() // it not works but I need this way
// self.tutorialScreenIsShowable = self.userLoginViewModel.loginButtonActionWithReturn() // it works, but its not good in this case
}) {
Text("Log in")
}
}
}
,
class UserLoginViewModel: NSObject, ObservableObject {
@Published var tutorialScreenIsShowable = false
func loginButtonAction() {
self.tutorialScreenIsShowable = true
}
func loginButtonActionWithReturn() -> Bool {
return true
}
}
据我所知,如果函数有一个可以工作的 return 值,但在这种情况下,有一个委托方法 运行 我可以在其中处理变量。
我想尽可能避免@EnvironmentObject,我希望有另一个解决方案。
你能帮我解决这个问题吗?
编辑:我简化了示例。并在此处上传示例项目:https://www.dropbox.com/s/paosp6iom9oks9p/InnerViewPropBind.zip
此行为的起源是 NavigationView
在更新期间多次重新创建自己的内容。
这是一个可能的解决方案 - 一些重新设计和所有权变更。
测试 Xcode 11.4 / iOS 13.4
struct AuthenticationView: View {
// keep model here to avoid recreation inside navigation view
@ObservedObject var userLoginViewModel = UserLoginViewModel()
var body: some View {
NavigationView {
ZStack {
// use binding directly in view model
NavigationLink(destination: Text("TutorialView"), isActive: $userLoginViewModel.tutorialScreenIsShowable) {
EmptyView()
}
UserLoginView(userLoginViewModel: userLoginViewModel)
}
}
}
}
struct UserLoginView: View {
@ObservedObject var userLoginViewModel: UserLoginViewModel
var body: some View {
Button(action: {
self.userLoginViewModel.loginButtonAction()
}) {
Text("Log in")
}
}
}
class UserLoginViewModel: NSObject, ObservableObject {
@Published var tutorialScreenIsShowable = false
func loginButtonAction() {
self.tutorialScreenIsShowable = true
}
func loginButtonActionWithReturn() -> Bool {
return true
}
}