swift fullScreenCover显示的是一张白纸,尽管没有抛出错误,并且尝试了多种修复方法

uqjltbpv  于 2023-06-21  发布在  Swift
关注(0)|答案(1)|浏览(63)

我正在尝试使用SwiftUI开发我的第一个全栈应用程序,我试图在一个名为“LoginView”的视图(用于处理用户登录)和一个名为DataInputView的视图(用于处理新用户Data的输入)之间导航。不幸的是,正在提交的表格是完全空白的。我是Swift的新手,所以请原谅糟糕的编码实践。以下是相关的代码。请忽略所有评论,因为它们是为潜在的未来合作开发者准备的,还有一些功能尚未完成。

//
//  UserMetaDataViewModel.swift

import Foundation
import FirebaseAuth
import FirebaseFirestore
import UIKit
import FirebaseStorage

@MainActor
class UserMetaDataViewModel: ObservableObject, Identifiable {
    
    @Published var userMetaData: UserMetaData
    
    init(userMetaData: UserMetaData = UserMetaData(id: "", email: "", nameFirst: "", nameLast: "", handle: "", gender: Gender.other, age: 0, bio: "", dataInputComplete: false)) {
        self.userMetaData = userMetaData
    } //Creates new userMetaData object with no params. This is how it will be done every time a new user is created. calling UserMetaDataViewModel() will create a new UserMetaData object with empty fields such that the program and database will be able to recognize "default data" and handle it accordingly. This data will then be updated with the saveUserData field, which takes an instance of UserMetaData.
    
    
    //TODO: updateField function which takes a metaData field as a parameter and updates the specific field in the metadata
    
    
    func saveUserData(userMetaData: UserMetaData) async -> String? {
        let db = Firestore.firestore()

        if let id = userMetaData.id {
            do {
                try await db.collection("userMetaData").document(id).setData(userMetaData.dictionary)
                print("Success in saving data for user \(userMetaData.nameFirst)")
                return nil // Indicate success with nil
            } catch {
                print("Error could not update data in 'userMetaData'")
                return error.localizedDescription // Return error message on failure
            }
        } else {
            print("Error could not create a new instance of UserMetaData: UID is nil")
            return "User ID is nil" // Return error message
        }
    }

    func loadUserData() async -> Bool {
        let db = Firestore.firestore()

        guard let userID = Auth.auth().currentUser?.uid else { return false }

        do {
            let document = try await db.collection("userMetaData").document(userID).getDocument()
            print("Document data: \(String(describing: document.data()))")
            
            if document.exists {
                do {
                    let loadedUserData = try document.data(as: UserMetaData.self)
                    self.userMetaData = loadedUserData
                    return true
                } catch {
                    print("Error decoding user data: \(error)")
                    return false
                }
            } else {
                print("Document not found")
                return false
            }
        } catch {
            print("Error loading user data: \(error.localizedDescription)")
            return false
        }
    }

    
    func saveProfilePic(userMetaData: UserMetaData, image: UIImage) async -> Bool {
        guard let userEmail = userMetaData.email else {
            print("error finding ID of userMetaData")
            return false
        }
        let photoName = UUID().uuidString
        let storage = Storage.storage()
        let storageRef = storage.reference().child("\(userEmail)/\(photoName).jpeg")
        
        guard let resizedImage = image.jpegData(compressionQuality: 0.2) else {
            print("Error, could not resize image")
            return false
        }
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpg"
        
        var imageURLString = ""
        do {
            let _ = try await storageRef.putDataAsync(resizedImage, metadata: metadata)
            do {
                let imageURL = try await storageRef.downloadURL()
                imageURLString = "\(imageURL)"
            } catch {
                print("Error: could not get ImageUrl after saving profile URL")
            }
            print("profile image saved")
        } catch {
            print("Error uploading image to firebase storage")
            return false
        }
        let db = Firestore.firestore()
        let collectionString = "email/\(userEmail)/profilePic"
        
       /* do {
            userMetaData.profilePictureURL = imageURLString
            try await db.collection(collectionString).document(photoName).set
        } catch {
        
        } */
        return true
    }
}
//
//  DataInputView.swift

import SwiftUI

struct DataInputView: View {
    @ObservedObject var userMetaDataVM: UserMetaDataViewModel

    var body: some View {
        Form {
            Section(header: Text("Enter Information")) {
                TextField("First", text: $userMetaDataVM.userMetaData.nameFirst)
                TextField("First", text: $userMetaDataVM.userMetaData.nameLast)
                TextField("Handle", text: $userMetaDataVM.userMetaData.handle)
                Picker("Gender", selection: $userMetaDataVM.userMetaData.gender) {
                    ForEach(Gender.allCases, id: \.self) {
                        Text($0.rawValue)
                    }
                }
                TextField("Age", value: $userMetaDataVM.userMetaData.age, formatter: NumberFormatter())
                TextField("Bio", text: $userMetaDataVM.userMetaData.bio)
            }

            Button(action: {
                Task {
                    if let email = userMetaDataVM.userMetaData.email {
                        _ = await userMetaDataVM.saveUserData(userMetaData: userMetaDataVM.userMetaData)
                    }
                }
            }) {
                Text("Continue")
            }
        }
    }
}


struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        DataInputView(userMetaDataVM: UserMetaDataViewModel(userMetaData: UserMetaData(id: "", email: "", nameFirst: "", nameLast: "", handle: "", gender: Gender(rawValue: "") ?? Gender.male, age: 10, bio: "", profilePictureURL: "", dataInputComplete: false)))
    }
}
//
//  UserMetaDataViewModel.swift

import Foundation
import FirebaseAuth
import FirebaseFirestore
import UIKit
import FirebaseStorage

@MainActor
class UserMetaDataViewModel: ObservableObject, Identifiable {
    
    @Published var userMetaData: UserMetaData
    
    init(userMetaData: UserMetaData = UserMetaData(id: "", email: "", nameFirst: "", nameLast: "", handle: "", gender: Gender.other, age: 0, bio: "", dataInputComplete: false)) {
        self.userMetaData = userMetaData
    } //Creates new userMetaData object with no params. This is how it will be done every time a new user is created. calling UserMetaDataViewModel() will create a new UserMetaData object with empty fields such that the program and database will be able to recognize "default data" and handle it accordingly. This data will then be updated with the saveUserData field, which takes an instance of UserMetaData.
    
    
    //TODO: updateField function which takes a metaData field as a parameter and updates the specific field in the metadata
    
    
    func saveUserData(userMetaData: UserMetaData) async -> String? {
        let db = Firestore.firestore()

        if let id = userMetaData.id {
            do {
                try await db.collection("userMetaData").document(id).setData(userMetaData.dictionary)
                print("Success in saving data for user \(userMetaData.nameFirst)")
                return nil // Indicate success with nil
            } catch {
                print("Error could not update data in 'userMetaData'")
                return error.localizedDescription // Return error message on failure
            }
        } else {
            print("Error could not create a new instance of UserMetaData: UID is nil")
            return "User ID is nil" // Return error message
        }
    }

    func loadUserData() async -> Bool {
        let db = Firestore.firestore()

        guard let userID = Auth.auth().currentUser?.uid else { return false }

        do {
            let document = try await db.collection("userMetaData").document(userID).getDocument()
            print("Document data: \(String(describing: document.data()))")
            
            if document.exists {
                do {
                    let loadedUserData = try document.data(as: UserMetaData.self)
                    self.userMetaData = loadedUserData
                    return true
                } catch {
                    print("Error decoding user data: \(error)")
                    return false
                }
            } else {
                print("Document not found")
                return false
            }
        } catch {
            print("Error loading user data: \(error.localizedDescription)")
            return false
        }
    }

    
    func saveProfilePic(userMetaData: UserMetaData, image: UIImage) async -> Bool {
        guard let userEmail = userMetaData.email else {
            print("error finding ID of userMetaData")
            return false
        }
        let photoName = UUID().uuidString
        let storage = Storage.storage()
        let storageRef = storage.reference().child("\(userEmail)/\(photoName).jpeg")
        
        guard let resizedImage = image.jpegData(compressionQuality: 0.2) else {
            print("Error, could not resize image")
            return false
        }
        let metadata = StorageMetadata()
        metadata.contentType = "image/jpg"
        
        var imageURLString = ""
        do {
            let _ = try await storageRef.putDataAsync(resizedImage, metadata: metadata)
            do {
                let imageURL = try await storageRef.downloadURL()
                imageURLString = "\(imageURL)"
            } catch {
                print("Error: could not get ImageUrl after saving profile URL")
            }
            print("profile image saved")
        } catch {
            print("Error uploading image to firebase storage")
            return false
        }
        let db = Firestore.firestore()
        let collectionString = "email/\(userEmail)/profilePic"
        
       /* do {
            userMetaData.profilePictureURL = imageURLString
            try await db.collection(collectionString).document(photoName).set
        } catch {
        
        } */
        return true
    }
}

我已经尝试确保没有并发问题,确保数据正确保存到firebase,并且身份验证工作正常。我真的不能告诉你为什么我不能得到适当的床单出现。

bmvo0sr5

bmvo0sr51#

当尝试使用视图模型对象而不是学习View结构时,通常会出现这种错误。首先,我建议删除:

@MainActor
class UserMetaDataViewModel: ObservableObject, Identifiable {

struct UserController {

这不应该是@MainActor,这样它的异步函数就可以在后台线程上运行。由于您没有使用合并,因此可以将其更改为结构并删除ObservableObject一致性。最后,在SwiftUI中,我们使用.task(id:)修饰符而不是Task { }
所以你应该得到这样的结果:

Button("Save") {
    metadataToSave = Metadata(email, firstName, lastName) // from text field states.
}
.disabled(metadataToSave != nil)
.task(id: metadataToSave) {
    if metadataToSave == nil {
        return
    }
    do {
        try await userController.saveUserData(userMetaData: metadataToSave)
    }
    catch {
        errorMessage = "Failed"
    }
    metadataToSave = nil
}

相关问题