首页 > 解决方案 > SwiftUI 在使用 Firebase 单击注销时隐藏 TabView

问题描述

我是一个带有 Firebase 登录/注销的简单应用程序。登录工作完美,当我注销 LoginView 时出现我的应用程序,但问题是 TabView 仍然存在,您可以导航到另一个选项卡。那么应该发生什么:标签栏应该是不可见/隐藏的,或者我的 LoginView 应该出现在其他所有内容上。

内容视图.swift

    var body: some View {
        if Auth.auth().currentUser == nil {
            LoginView()
        }
        else {
            AppView()
        }
    }

AppView.swift

var body: some View {
    TabView {
        PlacesView()
            .tabItem {
                Image(systemName: "mappin.and.ellipse")
                Text("Places")
            }
        MeetupsView()
            .tabItem {
                Image(systemName: "person.3")
                Text("Meetups")
            }
        ProfileView()
            .tabItem {
                Image(systemName: "person.crop.circle")
                Text("Profile")
            }
        SettingsView()
            .tabItem {
                Image(systemName: "gear")
                Text("Settings")
            }
    }
}

登录视图.swift

@State var signInSuccess = false

var body: some View {
    return Group {
        if signInSuccess {
            AppView()
        }
        else {
            LoginFormView(signInSuccess: $signInSuccess)
        }
    }
}

设置注销

NavigationView {
            if !signedIn {
                ContentView()
                    .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
                    .background(Color.red)
                    .edgesIgnoringSafeArea(.all)
            }
            else {
            List {
    Button(action: {
                    do {
                      try Auth.auth().signOut()
                        signedIn.toggle()
                    } catch let signOutError as NSError {
                      print ("Error signing out: %@", signOutError)
                    }
                    
                }){
                Text("Sign out")
                    .fontWeight(.light)
                        .foregroundColor(Color.red)
                        .frame(maxWidth: .infinity, alignment: .center)
                    .font(/*@START_MENU_TOKEN@*/.title2/*@END_MENU_TOKEN@*/)
                }
          }
     }

好像这

标签: firebaseswiftui

解决方案


ContentView不会知道触发对视图层次结构的更新,因为目前它无法理解 Auth.auth().currentUser 在用户注销时已更改值。

一种解决方案是使用 @ObservableObject 和 Firebase 的身份验证状态侦听器为您处理此问题:

class AuthManager : ObservableObject {
    @Published var isLoggedIn = false
    
    private var authStateHandle: AuthStateDidChangeListenerHandle?
    
    init() {
        authStateHandle = Auth.auth().addStateDidChangeListener { _, user in
            self.isLoggedIn = user != nil
        }
    }
}

然后,在 ContentView 中:

struct ContentView : View {
  @ObservedObject authManager = AuthManager()
  var body : some View {
    if authManager.isLoggedIn {
      AppView()
    } else {
      LoginView()
    }
  }
}

Firebase 提供的身份验证状态侦听器句柄的好处是它自动处理连接到全局 Auth() 实例,因此您甚至无需担心将其连接到您的登录或注销功能。这意味着您可能可以删除signInSuccess登录视图上的布尔检查,因为现在将在ContentView级别处理。


推荐阅读