首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将observableObject的属性从另一个observableObject更改

将observableObject的属性从另一个observableObject更改
EN

Stack Overflow用户
提问于 2022-10-24 07:48:51
回答 1查看 31关注 0票数 0

存在以下问题:必须为应用程序创建一个授权窗口,这是我发现的以下实现的最符合逻辑的解决方案(我不得不这样做,因为mainView有一个tabView,如果它在navigationView中的行为不正确)

代码语言:javascript
复制
struct ContentView: View {

@EnvironmentObject var vm: AppSettings

var body: some View {
    if vm.isLogin {
        MainView()
    } else {
        LoginView()
    }
}

AppSettings看起来是这样的:

代码语言:javascript
复制
struct MyApp: App {

    @StateObject var appSetting = AppSettings()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appSetting)
        }
    }
}
class AppSettings: ObservableObject {
    @Published var isLogin = false
}

默认情况下,将向用户显示如下所示的授权窗口:

代码语言:javascript
复制
struct LoginView: View {
    @StateObject var vm = LoginViewModel()
    var body: some View {
        NavigationView {
            VStack {
                TextField("Email", text: $vm.login)
                TextField("Password", text: $vm.password)
                
                Button {
                    vm.auth()
                } label: {
                    Text("SignIn")
                }
            }
        }
    }
}

最后,loginViewModel看起来是这样的:

代码语言:javascript
复制
class LoginViewModel: ObservableObject {
    
    @Published var login = ""
    @Published var password = ""
    
  //@Published var appSettings = AppSettings() -- error on the first screenshot
    //or
  //@EnvironmentObject var appSettings: AppSettings -- error on the second screenshot

    func auth() {
        UserAPI().Auth(req: LoginRequest(email: login, password: password)) { response, error in
            if let err = error {
                // Error Processing
            } else if let response = response {
                Defaults.accessToken = response.tokens.accessToken
                Defaults.refreshToken = response.tokens.refreshToken
                self.appSettings.isLogin = true
            }
        }
    }
}

1错误- 访问StateObject的对象而不安装在视图上。这将每次创建一个新实例。

2错误- ),因为AppSettings作为此视图的祖先可能会丢失

我请求帮助,我只是找不到一个方式来进行两个observableObject的交互。为了实现这样的功能,我不得不将所有的逻辑插入到按钮的操作中。

除了此功能外,还计划在各种情况下将isLogin变量更改为false或使用其他环境变量轻松实现其他函数,从而实现帐户的退出。

为了简单地解释情况,这个例子被刻意简化了。

EN

回答 1

Stack Overflow用户

发布于 2022-10-24 11:24:15

我认为只在顶层使用LoginViewModel是解决这一问题的最简单方法。但是,如果要同时保持这两种情况,可以使用.onChanged修饰符来同步它们。

代码语言:javascript
复制
class LoginViewModel: ObservableObject {
    
    @Published var login = ""
    @Published var password = ""
    
    @Published var isLogin = false
    
    func auth() {
        UserAPI().Auth(req: LoginRequest(email: login, password: password)) { response, error in
            if let err = error {
                // Error Processing
            } else if let response = response {
                Defaults.accessToken = response.tokens.accessToken
                Defaults.refreshToken = response.tokens.refreshToken
                isLogin = true
            }
        }
    }
}

struct LoginView: View {
    @StateObject var vm = LoginViewModel()
    // grab the AppSettings from the environment
    @EnvironmentObject var appSetting: AppSettings
    var body: some View {
        NavigationView {
            VStack {
                TextField("Email", text: $vm.login)
                TextField("Password", text: $vm.password)
                
                Button {
                    vm.auth()
                } label: {
                    Text("SignIn")
                }
                // synchronise the viewmodels here
                .onChange(of: vm.isLogin) { newValue in
                    appSetting.isLogin = newValue
                }
            }
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74177998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档