【发布时间】:2021-09-05 18:27:34
【问题描述】:
我目前正在构建一个带有登录/注册视图的简单应用,以便更好地了解如何将 SwiftUI 与 Firebase 集成。
我在尝试更新用户数据时遇到了一些问题。我注意到,在以一个用户身份注销然后以其他用户身份登录之后,在点击登录按钮后,在 FirstView 上更新用户信息之前会有一瞬间的延迟。我正在尝试弄清楚如何避免这种延迟的发生。
另一方面,我也无法弄清楚如何从我的 LoginView() 顺利导航到我的 FirstView()。我在 Navigation Stack 中有我的 FirstView(),但是视图之间的转换非常突然并且没有 NavigationLink 动画。我该如何解决这个问题?
非常感谢!
这里是相关代码...
@main
struct AWSupportLoggerApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
@StateObject var viewModel = AppViewModel()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(viewModel)
}
}
class AppDelegate:NSObject,UIApplicationDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
}
struct ContentView: View {
@EnvironmentObject var viewModel: AppViewModel
var body: some View {
NavigationView {
if viewModel.signedIn {
FirstView()
} else {
//.onAppear method is used for keyboard management (See Misc Functions...)
SignInView()
.onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
.navigationBarHidden(true)
}
}
.onAppear {
viewModel.listen()
}
}
}
class AppViewModel: ObservableObject {
private var db = Firestore.firestore()
@Published var userInfo: User?
@Published var signedIn: Bool = false
var handle: AuthStateDidChangeListenerHandle?
let authRef = Auth.auth()
var authHandle : AuthStateDidChangeListenerHandle?
var rootInfoCollection : CollectionReference!
var userIdRef = ""
func fetchUserData(){
db.collection("Users").document("\(userIdRef)").getDocument { document, error in
// Check for error
if error == nil {
// Check that this document exists
if document != nil && document!.exists {
self.userInfo = document.map { (documentSnapshot) -> User in
let data = documentSnapshot.data()
let uid = data?["uid"] as? UUID ?? UUID()
let company = data?["company"] as? String ?? ""
let name = data?["name"] as? String ?? ""
let admin = data?["admin"] as? Bool ?? false
let photo = data?["photo"] as? String ?? ""
return User(uid: uid, company: company, name: name, admin: admin, photo: photo)
}
}
}
}
}
func listen(){
handle = authRef.addStateDidChangeListener({ auth, user in
print(user?.email ?? "No User Found")
if let user = auth.currentUser {
self.userIdRef = user.uid
self.rootInfoCollection = Firestore.firestore().collection("/Users/")
DispatchQueue.main.async {
self.fetchUserData()
}
self.signedIn = true
} else {
self.signedIn = false
}
})
}
func signIn(email: String, password: String){
authRef.signIn(withEmail: email, password: password) { result, error in
guard result != nil, error == nil else {
return
}
}
}
func signOut(){
do {
try authRef.signOut()
} catch {
print(error)
}
}
func signUp(email: String, password: String, company: String, name: String, admin: Bool, photo: String){
authRef.createUser(withEmail: email, password: password) { result, error in
guard result != nil, error == nil else {
return
}
let db = Firestore.firestore()
//Success
db.collection("Users").document("\(result!.user.uid)").setData(["company" : "\(company)", "name" : "\(name)", "admin" : admin, "photo" : "\(photo)", "uid":result!.user.uid]) { error in
if error != nil {
print(error!)
}
}
}
}
func unbind() {
if let handle = handle {
authRef.removeStateDidChangeListener(handle)
}
}
}
struct FirstView: View {
@EnvironmentObject private var appViewModel: AppViewModel
var body: some View {
VStack{
Spacer()
VStack(spacing: 50){
NavigationLink(destination: Text("Test")){
awButton(content: "Request Support", backColor: Color(#colorLiteral(red: 0, green: 0.723585546, blue: 0.9907287955, alpha: 1)))
.shadow(color: Color.primary.opacity(0.5), radius: 20, x: 0, y: 20)
.rotation3DEffect(Angle(degrees:10), axis: (x: 10.0, y: 0, z: 0))
}
NavigationLink(destination: Text("Test")){
awButton(content: "Request Quote", backColor: Color(#colorLiteral(red: 0.9372549057, green: 0.3490196168, blue: 0.1921568662, alpha: 1)))
.shadow(color: Color.primary.opacity(0.5), radius: 20, x: 0, y: 20)
.rotation3DEffect(Angle(degrees:10), axis: (x: 10.0, y: 0, z: 0))
}
NavigationLink(destination: Text("Test")){
awButton(content: "Ticket Status", backColor: Color(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
.shadow(color: Color.primary.opacity(0.5), radius: 20, x: 0, y: 20)
.rotation3DEffect(Angle(degrees:10), axis: (x: 10.0, y: 0, z: 0))
}
}
Spacer()
}
.navigationBarBackButtonHidden(true)
.navigationTitle(appViewModel.userInfo?.company ?? "Test")
.navigationBarItems(leading: Button(action: {
appViewModel.signOut()
}) {
HStack {
Text("Sign Out")
}
},trailing: HStack{
Image(systemName: "bell")
.font(.system(size: 30))
// selectedImageArray.first!
// .resizable()
// .scaledToFit()
// .clipShape(Circle())
// .frame(width: 50, height: 50)
Text(appViewModel.userInfo?.name ?? "Tester")
.font(.system(size: 20))
})
}
}
【问题讨论】:
-
“我正在想办法避免这种延迟的发生。”我还没有完全阅读您的代码,但我预计延迟来自网络流量(登录调用或从 Firestore 加载数据)。如果是这种情况,则无法摆脱延迟 - 但您当然可以在网络调用完成之前显示加载指示器。
-
您的第二个问题应该拆分为一个单独的问题,以便可以独立解决。
标签: firebase google-cloud-firestore swiftui