使用 SwiftUI 成功登录后导航

Day*_*eed 2 ios firebase swift swiftui

我正在使用 Firebase 和 SwiftUI 以用户身份登录。我一切正常,但无法弄清楚用户成功登录后如何导航到下一页。导航链接对我来说似乎很奇怪,所以我想知道是否有其他方法可以导航到下一个视图。其中LoginView包含登录屏幕并LoginViewModel使用 Firebase 执行登录过程。问题是,如果我基于根视图中的变量返回视图,那么一旦打开根视图以外的任何视图,它就不会更改视图(即,如果我导航到登录视图,它不会转到按下登录按钮后的主视图)。

ContentView(显示所有其他视图的根视图):

import SwiftUI

struct ContentView: View {
    @StateObject var userLoggedIn = LoginViewModel()
    var body: some View {
        if !userLoggedIn.isLoggedIn {
            LoginView()
        }
        else {
            MainView()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

登录查看:

import SwiftUI
import FirebaseAuth

struct LoginView: View {
    
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var isEditing = false
    @State private var showPassword = false
    @State private var radius = 300
    
    private var canLogIn: Bool {
        return !email.isEmpty && !password.isEmpty
    }

    let loginView = LoginViewModel()
    
    @ViewBuilder
    var body: some View {
        
        return NavigationView(content: {
            
            VStack {
                Spacer()
                    .frame(height: 150)
                
                Text("PET SUPPORT").foregroundColor(Color.petSupportText)
                    .font(Font.custom("Permanent Marker", size: 36))
                    .padding()

                Group {
                    
                    HStack {
                        
                        Text("EMAIL")
                            .font(Font.custom("Permanent Marker", size: 18))
                            .padding(.top, 10)
                        
                        Spacer()
                        
                    }
                    
                    TextField("Email", text: $email) {
                        isEditing in self.isEditing = isEditing
                    }
                    .autocapitalization(.none)
                    .keyboardType(.emailAddress)
                    .disableAutocorrection(true)
                    .padding(.top, 20)
                    
                    Divider()
                        .foregroundColor(.black)
                    
                }

                
                Group {
                    
                    HStack {
                        
                        Text("PASSWORD")
                            .font(Font.custom("Permanent Marker", size: 18))
                            .padding(.top, 10)
                        
                        Spacer()
                        
                    }

                    ZStack {
                        if showPassword {
                            TextField("Password", text: $password)
                        }
                        else {
                            SecureField("Password", text: $password)
                        }
                    }
                    .frame(height: 20)
                    .autocapitalization(.none)
                    .overlay(Image(systemName: showPassword ? "eye.slash" : "eye").onTapGesture { showPassword.toggle() }, alignment: .trailing)
                    .disableAutocorrection(true)
                    .padding(.top, 20)
                    
                    Divider()
                        .foregroundColor(.black)
                    
                }
                
                Spacer();
                
                Group {
                    
                    Button(action: {
                            loginView.login(email: email, password: password)
                            radius = 2000
                            MainView()
                    }, label: {
                        Text("Login")
                    })
                        .foregroundColor(.white)
                        .font(Font.custom("Permanent Marker", size: 18.0))
                        .padding(.horizontal, 20)
                        .padding()
                        .background(Color.petSupportBlue)
                        .cornerRadius(70.0)
                        .disabled(!canLogIn)
                }
                
                Spacer()
            }
            .padding(.horizontal, 30)
            .ignoresSafeArea()
            
        })
        
    }
}
Run Code Online (Sandbox Code Playgroud)

登录视图模型:

import Foundation
import Firebase

class LoginViewModel: ObservableObject {
    
    @Published var isLoggedIn = false
    func login(email: String, password: String) {
        
        Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
            
            if let error = error {
                print(error.localizedDescription)
            } else {
                print("Logged In!")
                self.isLoggedIn = true
            }
        }
        
    }
    
}
Run Code Online (Sandbox Code Playgroud)

主视图:

import SwiftUI

struct MainView: View {
    var body: some View {
        Text("Hello, World!")
    }
}
Run Code Online (Sandbox Code Playgroud)

jn_*_*pdx 6

如果您不想处理NavigationLink,正如 @Paulw11 在评论中提到的那样,您可以根据您在ObservableObject. 您甚至可以添加动画/过渡。请参阅下面的简单示例:


class LoginManager : ObservableObject {
    @Published var isLoggedIn = false
    
    func login() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            withAnimation {
                self.isLoggedIn = true
            }
        }
    }
}

struct ContentView : View {
    @StateObject var loginManager = LoginManager()
    
    var body: some View {
        if loginManager.isLoggedIn {
            LoggedInView()
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .transition(.move(edge: .leading))
        } else {
            LoginView(loginManager: loginManager)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .transition(.move(edge: .leading))
        }
    }
}

struct LoginView : View {
    @ObservedObject var loginManager : LoginManager
    
    var body: some View {
        Button("Login") {
            loginManager.login()
        }
    }
}

struct LoggedInView : View {
    var body: some View {
        Text("Logged in!")
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我是你,我也可能会考虑使用 atauthStateListener并据此设置登录属性。这样,如果重新打开应用程序并且用户仍处于登录状态,他们将自动转换到登录页面。