Firebase for SWIFT iOS: returning nil value in function
You need to use closures as getDocument()
does not return synchronously.
func display(userid: String, handler: (String) -> Void) {
let docRef = db.collection("user").document(uid)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
if let displayName = document.get("username") as? String {
handler(displayName)
}
} else {
print("Document does not exist")
}
}
}
And use it like so:
self.myLabel.text = "Loading..."
display(userid: {USER_ID}) { [weak self] displayName in
print(displayName)
self.myLabel.text = displayName
}
Why function return nil FireBase Swift
You're returning downloadURL
before the asynchronous function within your callee function has finished execution.
At this point, it will have nil
value, which is correct.
You'll want to use a completion handler to return downloadURL
when its ready, like -
func storagePutData(uid: String, image: UIImage, success:@escaping (String?)->(), error: @escaping (Error?) -> Void) {
var downloadURL: String!
let imageName = NSUUID().uuidString
let uploadDara = UIImageJPEGRepresentation(image, 0.1)!
let ref = self.refStorage.child("usersProfileImage/\(uid)/\(imageName).png")
ref.putData(uploadDara, metadata: nil) { (metaDara, error) in
if let err = error {
error(err)
}
ref.downloadURL(completion: { (url, error) in
if let err = error {
error(err)
} else {
downloadURL = url?.absoluteString
success(downloadURL)
}
})
}
}
Why does this query return nil from Firestore
The getDocuments
callback gets called with two values (querySnapshot
and `error), only one of which will have a value.
You're ignoring the error
and assuming that querySnapshot
has a value, which not only leads to the error you get, but also hides the likely cause.
I recommend following the pattern used in this example from the Firestore documentation on getting documents:
db.collection("cities").whereField("capital", isEqualTo: true)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
print("\(document.documentID) => \(document.data())")
}
}
}
By logging the error
you can see what went wrong with your getDocuments()
call.
Firebase returns nil when fetching data
When you observe a .value event for a list of nodes, you need to loop over snapshot.children
to get the individual nodes. From the documentation on listening for value events for lists:
_commentsRef.observe(.value) { snapshot in
for child in snapshot.children {
...
}
}
The ...
is where your current code inside the .childAdded
listener goes.
Current Firebase User Returning Nil
This typically means that the currentUser
is not yet initialized by the time that code runs. Since restoring the user's sign-in state requires a call to the server, it is an asynchronous operation.
Any code that depends on the current user state being restored should be inside (or be called from) an addStateDidChangeListener
as in your first snippet. So you may need a snippet like that in your other view controller(s) too.
Related Topics
How to Compare Two Strings to Check If They Have Same Characters Swift 4
How to Get All Text from a PDF in Swift
Custom Cell with Uitableview Inside Uicollectionviewcell
Simple Swift Class Does Not Compile
Passing Unknown Number of Arguments in a Function
Why Does Function Has Multiple Return Types in Swift
Swift Alamofire Return Value Is Empty
Swift: Can't Edit Properties of Custom Table Cell Programmatically
Comparing Objects in an Array Extension Causing Error in Swift
Swift Switch Char{ Case "\U{E2}:
How to Run the Simulator the Operation Couldn't Be Completed. (Launchserviceserror Error 0.)
Swift Check If Value Is of Type Array (Of Any Type)
Auth.Auth().Currentuser.Reload() Doesn't Refresh Currentuser.Isemailverified
What Does the Underscore in a Function Declaration Do
Accessing Actor Properties Synchronously from Task-Less Context