【发布时间】:2020-05-11 13:51:16
【问题描述】:
我正在 IOS 上构建我的第一个应用,使用 SwiftUI 和 Firebase 进行身份验证和存储
对于登录,我使用默认的 Firebase UI,它是通过 FUIAuthPickerViewController 的子类自定义的,称为 MyFUIAuthPickerViewController,详见https://firebase.google.com/docs/auth/ios/firebaseui
defaultUI 已初始化并显示在场景委托文件中。
// Create the SwiftUI view that provides the window contents.
//let contentView = ContentView()
self.authUI = _createAuthUI()
guard self.authUI != nil else {
print("No authUI")
return
}
self.authUI?.delegate = self
self.authUI?.shouldHideCancelButton = true
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
//window.rootViewController = UIHostingController(rootView: contentView)
window.rootViewController = UINavigationController(rootViewController: MyFUIAuthPickerViewController(authUI: authUI!))
self.window = window
window.makeKeyAndVisible()
}
MyFUIAuthPickerViewController 子类目前包含的内容不多,但将用于为授权屏幕添加默认背景
import Foundation
import FirebaseUI
import Firebase
class MyFUIAuthPickerViewController: FUIAuthPickerViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
为了跟踪用户是否登录,我使用了一个名为 Sessionstore 的 Observable 对象。我改编自 https://benmcmahen.com/authentication-with-swiftui-and-firebase/ 的代码,它使用的是旧式 Bindable 协议
import Foundation
import SwiftUI
import Firebase
import Combine
class SessionStore : ObservableObject
{
@Published var user: AppUser?
var handle: AuthStateDidChangeListenerHandle?
func listen () {
// monitor authentication changes using firebase
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
if let user = user {
// if we have a user, create a new user model
print("Got user: \(user) \(user.displayName!)")
self.user = AppUser(uid: user.uid,displayName: user.displayName, email: user.email)
} else {
// if we don't have a user, set our session to nil
self.user = nil
}
}
}
func signOut () -> Bool {
do {
try Auth.auth().signOut()
print("signed out")
self.user = nil
print("user object set to nil")
return true
} catch {
print("Problem encountered signing the user out")
return false
}
}
}
环境对象出现在我的内容视图和场景代理中
场景委托
class SceneDelegate: UIResponder, UIWindowSceneDelegate, FUIAuthDelegate{
var window: UIWindow?
var authUI: FUIAuth?
@EnvironmentObject var appSession: SessionStore
内容视图
import SwiftUI
import FirebaseUI
struct ContentView: View {
@EnvironmentObject var session: SessionStore
var body: some View {
Group{
if session.user != nil {
Text("Welcome \(session.user!.displayName!)")
} else {
Text("Please login")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
let nav = UINavigationController()
static var previews: some View {
ContentView().environmentObject(SessionStore())
}
}
在我的 sceneDelegate 扩展中,我实现了所需的 firebase 功能。 成功登录后,我创建了一个新的 appuser 对象,将其放置在 sessionStore 中,然后将 rootviewcontroller 更改为在 environmentObject 中传递的 contentview
Extension SceneDelegate {
func authUI(_ authUI: FUIAuth, didSignInWith user: User?, error: Error?) {
guard user != nil else {
print("No User")
return
}
print(user!.displayName!)
let user = AppUser(uid: user!.uid,displayName: user?.email,email: user?.displayName)
self.appSession.user = user
let contentView = ContentView()
self.window?.rootViewController = UIHostingController(rootView: contentView.environmentObject(SessionStore()))
self.window?.makeKeyAndVisible()
}
func authPickerViewController(for authUI: FUIAuth) -> FUIAuthPickerViewController {
return MyFUIAuthPickerViewController(authUI: authUI)
}
}
现在当我测试我的应用程序时,输入用户名和密码后出现以下错误
致命错误:未找到类型为 SessionStore 的 ObservableObject。 SessionStore 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失。:文件 /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-39.4.3/Core/EnvironmentObject.swift ,第 55 行
我怀疑这与从我的 sceneDelegate 到 ContentView 的流之间的 MyFUIAuthPickerViewController 中 de environmentObject 丢失的事实有关,但我如何防止这种情况发生?我需要以某种方式扩展 MyFUIAuthPickerViewController 以允许传递 environmentObject 但如何?
希望我的问题很清楚,你们可以提供帮助。
【问题讨论】:
-
我不确定发生了什么,但您使用
environmentObject窗口的根视图创建了ContentView,因此您的MyFUI...VC不会妨碍您。几个方面:@EnvironmentObject在SceneDelegate上没有做任何事情。它仅适用于视图。此外,如果您使用guard let user = user ...,那么您不必在整个函数中继续使用!。 -
你能解决这个问题吗?我正在经历类似的事情
标签: ios swift firebase observable