我如何将此值从封闭式中提取以在Swift中更新Cutom对象



我正在使用Firestore后端构建AM应用程序,我试图将文档拨打,并使用当前用户的设置页面上的信息来调整文档。在更新空数组时,我可以做到这一点,但是尝试填充单个文档的时间很糟糕。我有一个称为DxUser的自定义对象:

struct DxUser {
    var email:String?
    var name:String?
    var timeStamp:Date?
    var profileImageURL:String?
    var ehr: String?
    var dictionary:[String:Any]? {
        return [
            "email":email,
            "name":name,
            "timeStamp":timeStamp,
            "profileImageURL":profileImageURL,
            "ehr": ehr as Any
        ]
    }
}

extension DxUser : DocumentSerializable {
    init?(dictionary: [String : Any]) {
        guard let email = dictionary["email"] as? String,
            let name = dictionary["name"] as? String,
            let timeStamp = dictionary["timeStamp"] as? Date,
            let profileImageURL = dictionary["profileImageURL"] as? String,
            let ehr = dictionary["ehr"] as? String else {return nil}
        self.init(email: email, name: name, timeStamp: timeStamp, profileImageURL: profileImageURL, ehr: ehr)
    }
}

在视图控制器中,我试图与当前用户更新此变量,但是我只能在闭合中抓住它,并且它在块外的任何地方都填充了零。这是我正在使用的基本代码,但是谁能告诉我我缺少什么?

class SettingsController: UIViewController {
var dxUser = DxUser()

override func viewDidLoad() {
    super.viewDidLoad() 
    fetchUser()
}
func fetchUser() {
    guard let uid = Auth.auth().currentUser?.uid else {
        return
    }
    let userRef = db.collection("users").document(uid)
    userRef.getDocument { (document, error) in
        if error != nil {
            print(error as Any)
        } else {
            self.dxUser = DxUser(dictionary: (document?.data())!)!
            self.navigationItem.title = self.dxUser.name
            print (self.dxUser)
        }
    }
}

是的,这就是我在表观上进行操作的方式,但是我在常规VC上没有看到任何可比的东西。

db.collection("users").document(uid!).collection("goals").getDocuments { (snapshot, error) in
        if error != nil {
            print(error as Any)
        } else {
            //set the profile array to equal whatever I am querying below
            goalsArray = snapshot!.documents.flatMap({Goal(dictionary: $0.data())})
            DispatchQueue.main.async {
                self.collectionView?.reloadData()
            }
        }
    }

与您可以访问dxuser的位置不多。这是时间。Firebase API是异步的,这意味着userRef.getDocument()立即返回,并且您仅在请求完成后才收到回调。如果您尝试在fetchUser()方法中访问该呼叫后立即访问dxUser,则它将无法使用,因为请求尚未完成。鉴于ASYNC API的工作方式,您应仅使用dxUser 调用回调,这通常意味着延迟应用程序中该数据的渲染(例如打印语句的位置(。

请在这里阅读更多有关为什么Firebase API异步以及您对它们的期望的信息。

我实际上弄清楚了。我将fetchuser((函数拉出到viewwillappear函数,所以在视图出现之前,我将其调用。然后,我执行了异步函数以重新运行ViewDidload。其他人有更好的建议?

    override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(true)
      fetchUser()
    }
    func fetchUser() {
      let userRef = db.collection("users").document(uid)
      userRef.getDocument { (document, error) in
          if error != nil {
              print(error as Any)
          } else {
              self.dxUser = DxUser(dictionary: (document?.data())!)!            
              DispatchQueue.main.async {
                  self.viewDidLoad()
              }     
              self.navigationItem.title = self.dxUser.name
          }
      }
  }

最新更新