ios SwiftUI NavigationLink不会使用onReceive方法触发

lf3rwulv  于 2022-12-24  发布在  iOS
关注(0)|答案(3)|浏览(124)

我正在尝试学习如何使用Firebase在Swift中进行基本登录,这让我在登录完成后无法导航到应用程序的主页。我有一个ViewModel来管理登录,我在视图中添加了一个onReceive属性来监听viewModel的布尔值,以检测登录并触发导航。我不明白为什么它不工作,任何帮助都将不胜感激!
视图模型:

class LoginViewModel: ObservableObject {
    let auth = Auth.auth()
    var userInfo: User?
    
    @Published var isSignedIn = false
    
    func signIn(email: String, password: String) {
        auth.signIn(withEmail: email, password: password) { _, error in
            if let error = error as? NSError {
                print("Error happened on login"+error.description)
            } else {
                print("Login successful")
                if let user = self.auth.currentUser {
                    print("We have a user")
                    self.userInfo = user
                    self.isSignedIn.toggle()
                }
            }
        }
    }
}

查看:

struct LoginPage: View {
    @State var email = ""
    @State var password = ""

    @ObservedObject var viewModel = LoginViewModel()

    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    TextField("Email", text: $email).padding()
                        .background(Color(.secondarySystemBackground))
                        .padding()
                    TextField("Password", text: $password).padding()
                        .background(Color(.secondarySystemBackground))
                        .padding()
                    Button(action: {
                        guard !email.isEmpty, !password.isEmpty else {
                            return
                        }
                        viewModel.signIn(email: email, password: password)

                    }, label: {
                        Text("Sign in")
                            .padding(EdgeInsets(top: 12, leading: 35, bottom: 12, trailing: 35))
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(15)
                    })
                }
            }.navigationTitle("Login")
        }.onReceive(viewModel.$isSignedIn) { isSignedIn in
            if isSignedIn {
                print("ok damm")
                NavigationLink(destination: HomePage()) {
                    EmptyView()
                }
            }
        }
    }
}

请注意,每次都打印“ok damm”。

fzsnzjdm

fzsnzjdm1#

尝试下面的代码,它将帮助您解决您的问题:

NavigationLink(destination: Text("Second View"), isActive: $isSignedIn){
                EmptyView()
            }

查看:

struct LoginPage: View {
    @State var email = ""
    @State var password = ""

    @ObservedObject var viewModel = LoginViewModel()

    var body: some View {
        NavigationView {
            ZStack {
                VStack {
                    TextField("Email", text: $email).padding()
                        .background(Color(.secondarySystemBackground))
                        .padding()
                    TextField("Password", text: $password).padding()
                        .background(Color(.secondarySystemBackground))
                        .padding()
                    Button(action: {
                        guard !email.isEmpty, !password.isEmpty else {
                            return
                        }
                        viewModel.signIn(email: email, password: password)

                    }, label: {
                        Text("Sign in")
                            .padding(EdgeInsets(top: 12, leading: 35, bottom: 12, trailing: 35))
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(15)
                    })
                }

              NavigationLink(destination: HomePage()), isActive: $isSignedIn){
                EmptyView()
            }
            }.navigationTitle("Login")
        }
    }
}
i2byvkas

i2byvkas2#

Jatin Bhuva的回答可以使用,但在iOS 16中已弃用。以下是适用于新iOS版本的解决方案:

struct LoginPage: View {
    @State var email = ""
    @State var password = ""

    @ObservedObject var viewModel = LoginViewModel()

    var body: some View {
        NavigationStack {
            ZStack {
                VStack {
                    TextField("Email", text: $email).padding()
                        .background(Color(.secondarySystemBackground))
                        .padding()
                    TextField("Password", text: $password).padding()
                        .background(Color(.secondarySystemBackground))
                        .padding()
                    Button(action: {
                        guard !email.isEmpty, !password.isEmpty else {
                            return
                        }
                        viewModel.signIn(email: email, password: password)

                    }, label: {
                        Text("Sign in")
                            .padding(EdgeInsets(top: 12, leading: 35, bottom: 12, trailing: 35))
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(15)
                    })
                    Text("Don't have an account yet ?").padding(EdgeInsets(top: 20, leading: 0, bottom: 10, trailing: 0))
                    Button(action: {
                        guard !email.isEmpty, !password.isEmpty else {
                            return
                        }
                        viewModel.signUp(email: email, password: password)
                    }, label: {
                        Text("Create an account")
                            .padding(EdgeInsets(top: 12, leading: 35, bottom: 12, trailing: 35))
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(15)
                    })
                }
            }.navigationTitle("Login")
                .navigationDestination(isPresented: $viewModel.isSignedIn) {
                    HomePage()
                }
        }
    }
}

请注意我是如何用NavigationStack替换NavigationView的,并添加了.navigationDestination(isPresented:)来侦听模型的isSignedIn published属性的更改的。

hsvhsicv

hsvhsicv3#

swiftui中switch语句可以很容易地处理这个问题,我一直在使用它;

//Added code
enum LoginStages {
    case preLogin, postLogin
}

class LoginViewModel: ObservableObject {
    let auth = Auth.auth()
    var userInfo: User?
    @Published var loginStage: LoginStages = LoginStages.preLogin 
//Added code

    @Published var isSignedIn = false

func signIn(email: String, password: String) {
    auth.signIn(withEmail: email, password: password) { _, error in
        if let error = error as? NSError {
            print("Error happened on login"+error.description)
        } else {
            print("Login successful")
            if let user = self.auth.currentUser {
                print("We have a user")
                self.userInfo = user
                self.isSignedIn.toggle()
                loginStage = .postLogin //Added code
              }
           }
        }
     }
  }

您的视图应该是这样的;

struct LoginPage: View {
  @State var email = ""
  @State var password = ""

  @ObservedObject var viewModel = LoginViewModel()

  var body: some View {
   switch viewModel.loginStage {
   case .preLogin:
   //This is ur initial code which the user sees before login.
   // the same as the code you have above.
  case .postLogin:
  //Here, just call the post login view after a successful login;
  // I am assuming it is called home view for this example.
  HomeView()
 
    }
  }
}

相关问题