我正在构建一个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)
}
}
在视图控制器中,我试图用当前用户更新这个变量,但是我只能在闭包中获取它,并且它在块之外的任何地方填充为nil。这是我正在使用的基本代码,但有谁能告诉我缺少什么吗?
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的位置无关。是时候了。firebaseapi是异步的,这意味着userRef.getDocument()
会立即返回,并且只有在请求完成后才会收到回调。如果您尝试在调用之后在dxUser
方法中访问fetchUser()
,它将不可用,因为请求未完成。鉴于异步api就是这样工作的,您应该只在调用回调之后使用dxUser
,这通常意味着延迟应用程序中数据的呈现(例如print语句所在的位置)。
Please read more here关于为什么firebaseapi是异步的,以及您对它们的期望。