【问题标题】:How to handle retrieving user asynchronously from Firestore in Swift如何在 Swift 中处理从 Firestore 异步检索用户
【发布时间】:2020-06-19 15:41:29
【问题描述】:

我有一个使用 Firebase 进行用户处理的 Swift 应用。我还有一个 User 类,其中包含当前用户的单例。我试图在应用程序中的 ViewControllers 发生任何事情之前在场景委托中设置这个单例,但是我在从 Firestore 异步检索数据时遇到问题。在我的主视图控制器中,我尝试使用当前用户的名称设置标签的文本,但我收到没有当前用户的错误,因此在调用 viewDidLoad 时尚未设置。我的场景代表如下所示:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }

        if let currentUser = Auth.auth().currentUser {

            print("user is logged in")
            print("current user uid: @!", currentUser.uid)


            UserService.getUserData(uid: currentUser.uid) { (data) in
                if let data = data {
                    print(data.keys)
                    let myUser = User(uid: currentUser.uid, data: data)
                    User.setCurrent(myUser)
                    print("User was set")

                    let storyboard = UIStoryboard(name: "Main", bundle: .main)

                    if let initialViewController = storyboard.instantiateInitialViewController() {

                        self.window?.rootViewController = initialViewController
                        self.window?.makeKeyAndVisible()
                    }

                } else {
                    print("Error retrieving user data")
                }
            }

        } else {

            let initialViewController = UIStoryboard.initalViewController(for: .login)
            self.window?.rootViewController = initialViewController
            self.window?.makeKeyAndVisible()

        }

    }

我的 getUserData 函数:

static func getUserData(uid: String, _ completion: @escaping (_ data: [String: Any]?) -> Void ) {
        print("getUserData called")
        let userRef = Firestore.firestore().collection(Constants.Firestore.Collections.users)
        let userDocRef = userRef.document(uid)

        userDocRef.getDocument { (document, error) in
            guard let document = document, document.exists else {
                print("document does not exist")
                completion(nil)
                return
            }
            print("code is here")
            completion(document.data())
        }
    }

还有我的 HomeVC viewDidLoad 方法:

override func viewDidLoad() {
        super.viewDidLoad()
        availabilitySwitch.isOn = false
        print("Home view loaded")
        let first = User.current.firstName
        welcomeLabel.text = "Welcome Back, " + first + "!"
        // Do any additional setup after loading the view.

    }

知道如何在调用之前获取用户数据吗?

【问题讨论】:

    标签: swift firebase asynchronous


    【解决方案1】:

    HomeVC中创建一个属性

    var username = ""
    

    如果不为空,则在viewDidLoad 中显示该属性的值。

    override func viewDidLoad() {
        super.viewDidLoad()
        availabilitySwitch.isOn = false
        print("Home view loaded")
        if !username.isEmpty {
            welcomeLabel.text = "Welcome Back, " + username + "!"
        }
    }
    

    scene(_ scene: UIScene, willConnectTo中实例化视图控制器后分配用户名

    ...
    UserService.getUserData(uid: currentUser.uid) { (data) in
        if let data = data {
            print(data.keys)
            let myUser = User(uid: currentUser.uid, data: data)
            User.setCurrent(myUser)
            print("User was set")
    
            let storyboard = UIStoryboard(name: "Main", bundle: .main)
    
            if let initialViewController = storyboard.instantiateInitialViewController() {
                (initialViewController as! HomeVC).username = myUser.firstName
                self.window?.rootViewController = initialViewController
                self.window?.makeKeyAndVisible()
            }
    
        } else {
            print("Error retrieving user data")
        }
    }
    ...
    

    【讨论】:

    • 刚试了一下,给了我错误,“无法将'UINavigationController'类型的值转换为'Myapp.HomeVC'”在行:(initialViewController as! HomeVC).username = myUser.firstName
    • 这只是一个猜测。您必须获取主视图控制器的实例。这取决于设计,代码中没有信息。也许((initialViewController as! UINavigationController).topViewController as! HomeVC)
    • 现在可以了,谢谢!唯一的问题是,在被用户的名字替换之前,主视图会用 [User] 占位符闪烁。知道如何等待加载视图,直到加载第一个名称?
    猜你喜欢
    • 2019-02-25
    • 2021-03-27
    • 2021-02-26
    • 2019-01-28
    • 1970-01-01
    • 2020-09-03
    • 2019-01-11
    • 2019-05-02
    • 2017-03-02
    相关资源
    最近更新 更多