如何从闭包中提取此值以更新Swift中的cutom对象?

时间:2018-02-19 23:41:16

标签: swift firebase object closures google-cloud-firestore

我正在使用Firestore后端构建应用程序,并且我尝试使用当前用户的设置页面信息调用文档。在更新空数组时,我能够做到这一点没有问题,但是在尝试填充单个文档时遇到了可怕的时间。我有一个名为template<typename T1, typename T2> void func(T1, T2) = delete; long func(long a, long b) { static_assert(std::is_same<long,decltype(a+b)>::value,"!!"); return a+b; } 的自定义对象:

DxUser

在视图控制器中,我正在尝试使用当前用户更新此变量,但我只能在闭包中抓取它,并且它在块外的任何位置填充为nil。这是我正在使用的基本代码,但任何人都可以告诉我我错过了什么吗?

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)
    }
}

是的,这就是我在桌面视图中的表现方式,但我没有看到常规VC上的任何可比性。

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)
        }
    }
}

2 个答案:

答案 0 :(得分:1)

与您访问dxUser的位置位置并非如此。这是时间。 Firebase API是异步的,这意味着userRef.getDocument()会立即返回,并且只有在请求完成后才会收到回调。如果您在dxUser方法中尝试在该呼叫后立即访问fetchUser(),则该请求将无法使用,因为请求未完成。鉴于异步API的工作原理,您应该只在调用调用后调用dxUser ,这通常意味着延迟在您的应用中呈现该数据(例如您的print语句所在的位置)

Please read more here了解为什么Firebase API是异步的,以及您可以从中获得什么。

答案 1 :(得分:0)

我实际上已经明白了。我将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
          }
      }
  }