我正在使用SwiftUI和Firebase在IOS上构建我的第一个应用程序,以进行身份验证和存储
对于登录,我使用默认的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/的代码,该代码使用的是旧版的可绑定协议
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
}
}
}
环境对象出现在我的contentview和scenedelegate中
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中的environmentObject丢失有关,但是我如何防止这种情况发生呢?我需要以某种方式扩展MyFUIAuthPickerViewController,以允许环境对象的传递,但是如何传递?
希望我的问题很清楚,你们可以帮忙。
答案 0 :(得分:0)
您在SceneDelegate中的代码为let contentView = ContentView()
,我认为它应该类似于let contentView = ContentView().environmentObject(SessionStore())
似乎您的SessionStore也缺少var didChange = PassthroughSubject<SessionStore, Never>()
SessionStore的第一行应类似于:
import Foundation
import SwiftUI
import Firebase
import Combine
class SessionStore : ObservableObject
{
@Published var user: AppUser? { didSet { self.didChange.send(self) }}
var didChange = PassthroughSubject<SessionStore, Never>()
var handle: AuthStateDidChangeListenerHandle?
您要确保更改正在传播到侦听器(订户)。
如果我是正确的,@EnvironmentObject var appSession: SessionStore
不应在SceneDelegate中提及