在子视图中更新 ObservableObject 的 @Published 变量

39f*_*edy 16 swift swift5 swiftui

isLoggedIn在 ObservableObject 类中有一个已发布的变量,如下所示:

import Combine

class UserAuth: ObservableObject{
    @Published var isLoggedIn: Bool = false
}
Run Code Online (Sandbox Code Playgroud)

我想在特定视图 (LoginView) 中将此变量更新为 true。此变量决定了我向用户显示的视图,具体取决于用户是否已登录:

struct ContentView: View {
    @ObservedObject  var userAuth = UserAuth()
    var body: some View {
        Group{
            if(userAuth.isLoggedIn){
                MainView()
            }else{
                AccountView()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因为userAuth.isLoggedIn是false(我还没登录)AccountView就显示出来了。

账户视图:

struct AccountView: View {
    @State private var toggleSheet = false
    var body: some View {
        VStack {
            Spacer()
            Button(action: {
                self.toggleSheet.toggle()
            }){
                Text("Toggle Modal")
                    .padding()
                    .foregroundColor(Color.white)
                    .background(Color.blue)
                    .cornerRadius(10)
            }
            .sheet(isPresented: self.$toggleSheet){
                LoginView()
            }
            Spacer()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

每当用户按下按钮时,LoginView 模式就会显示:

struct LoginView: View {
    var body: some View {
        VStack{
            Button(action: {
                return self.login()
            }){
                Text("Log in")
                    .padding()
                    .foregroundColor(Color.white)
                    .background(Color.green)
                    .cornerRadius(10)
            }
        }
    }

    func login(){
        // update UserAuth().isLoggedIn to TRUE
    }
}
Run Code Online (Sandbox Code Playgroud)

在 LoginView 中有一个按钮,我想要的逻辑是让用户按下按钮,login()被调用并在该函数内部userAuth.isLoggedIn设置为true. 实现这一点的最佳方法是什么?

我试图直接更改该值,但出现以下错误:

Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive
Run Code Online (Sandbox Code Playgroud)

J. *_*ell 34

尝试将您的代码嵌入到 DispatchQueue.main.async 中,如下所示:

func login(){
    DispatchQueue.main.async {
        //update UserAuth().isLoggedIn to TRUE
    }
}
Run Code Online (Sandbox Code Playgroud)