I'm new to Swift/App development and am trying to learn how to work with a Firestore database. I am getting a response from Firestore and I'm able to print out the results. I don't know how to manipulate or use the data that I am receiving. I suspect it's something to do with the data type, I think Firestore provides the data back as a dictionary.
I want to be able to take the results from Firestore and but it into a if/switch statement and check if the input is true or false.
let db1 = Firestore.firestore()
db1.collection("firstDatabase").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
print("\(document.documentID) => \(document.data())")
}
}
How would I go about this after receiving the data? Would I assign to a variable first then manipulate it in an If/Switch statement to check if the values are true or false?
I know I'm missing some basics but thank you in advance for helping a new coder!
Just create a dictionary with the data you are receiving from Firestore like this:
let dictionary = document.data() as [String : Any]
then check the dictionary values in you if or switch statements:
if dictionary["foo"] {
//Do something here
}
if values for the dictionary are not bool:
if dictionary["foo"] == "bar" {
//Do something here
}
Related
let reference = Firestore
.firestore()
.collection(FBKeys.CollectionPath.users)
.document(uid)
reference.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document?.data()
print("Document data: \(dataDescription)")
} else {
print("Document does not exist")
}
}
I have created a cloud database using firebase. I have collection name is "users" and I have email, favoriteArtsts, name, uid as the fields. What I want to do is I want to add more artists to the favoriteArtsts array. However, to do so, I have to first get the reference to the array. By following the firebase instructions, I was able to get the user_id. The code above is the code I have tried. The code shows all the fields. However, I don't know how to get the favoriteArtsts values only. Is there a way to get the favoriteArtsts values?
You can get a single field by doing document.get("favoriteAritsts") (notice your typo in favoriteAritsts in your screenshots.
You can also do document.data()["favoriteAritsts"]
Both of the above will give you a return type of Any? so you would need to do any optional cast of either one with as? [String]:
let array = document.get("favoriteAritsts") as? [String]
Unable to fetch list of users from firebase. print returns as [] . Code is below. Any help would be awesome!
let COLLECTION_USERS = Firestore.firestore().collection("users")
func fetchUsers() {
COLLECTION_USERS.getDocuments { snapshot, _ in
guard let documents = snapshot?.documents else {return}
self.users = documents.compactMap({try? $0.data(as: User.self)})
print(self.users)
}
I expect the 7 users that I have signed up to print that data.
If documents.count shows that you've got 7 documents, but self.users contains no elements after running the mapping, this indicates your Firestore documents can't be mapped to your Swift structs.
Please make sure that the data types on your Swift structs match the types used in your Firestore documents.
You should also use code that is more error-resilient. In your code, you explicitly drop the error parameter on the closure - you rather don't want to do this.
The following code snippet (taken from the official docs) shows how to do this.
let docRef = db.collection("cities").document("BJ")
docRef.getDocument { (document, error) in
// Construct a Result type to encapsulate deserialization errors or
// successful deserialization. Note that if there is no error thrown
// the value may still be `nil`, indicating a successful deserialization
// of a value that does not exist.
//
// There are thus three cases to handle, which Swift lets us describe
// nicely with built-in Result types:
//
// Result
// /\
// Error Optional<City>
// /\
// Nil City
let result = Result {
try document?.data(as: City.self)
}
switch result {
case .success(let city):
if let city = city {
// A `City` value was successfully initialized from the DocumentSnapshot.
print("City: \(city)")
} else {
// A nil value was successfully initialized from the DocumentSnapshot,
// or the DocumentSnapshot was nil.
print("Document does not exist")
}
case .failure(let error):
// A `City` value could not be initialized from the DocumentSnapshot.
print("Error decoding city: \(error)")
}
}
In Swift, to retrieve an array from Firestore I use:
currentDocument.getDocument { (document, error) in
if let document = document, document.exists {
let people = document.data()!["people"]
print(people!)
} else {
print("Document does not exist")
}
}
And I receive data that looks like this
(
{
name = "Bob";
age = 24;
}
)
However, if I were to retrieve the name alone, normally I'd do print(document.data()!["people"][0]["name"]).
But the response I get is Value of type 'Any' has no subscripts
How do I access the name key inside that object inside the people array?
The value returned by document.data()!["people"] is of type Any and you can't access [0] on Any.
You'll first need to cast the result to an array, and then get the first item. While I'm not a Swift expert, it should be something like this:
let people = document.data()!["people"]! as [Any]
print(people[0])
A better way of writing #Frank van Puffelen's answer would be:
currentDocument.getDocument { document, error in
guard error == nil, let document = document, document.exists, let people = document.get("people") as? [Any] else { return }
print(people)
}
}
The second line may be a little long, but it guards against every error possible.
I have this code here and I want to delete certain value inside the array "Answered". Is there a simple way to access the first value in the array? This is right but shows what I want to happen "Answered[0]" <- I want to get the first value in that array and delete it. Thank you in Advance
let uid = Auth.auth().currentUser?.uid
print(self.randomArray)
let wash = db.collection("users").document(uid!)
wash.updateData([
"Answered": FieldValue.arrayUnion([self.randomArray])
])
}
if(self.check.isEmpty != true){
self.whichQuestion = self.check[0]
self.whichQuestionString = String(self.whichQuestion)
db.collection("users").document(uid!).updateData([
"Answered": FieldValue.delete(),
]) { err in
if let err = err {
print("Error updating document: \(err)")
} else {
print("Document successfully updated")
}
}
If your array contains unique values however, you can remove the item with:
self.whichQuestionString = String(self.whichQuestion)
db.collection("users").document(uid!).updateData([
"regions": FieldValue.arrayRemove([whichQuestionString])
])
If you only know the index of the item, there is no way to remove it without knowing the entire array.
The recipe for this is:
Read the document from Firestore
Modify the array in your application code
Write the entire modified array back to Firestore
Also see (none of which unfortunately are for Swift):
Is there any way to update a specific index from the array in Firestore
Delete data from Firestore dynamically
I am still new in swift development, my problem is, I have Firestore structure as below:
the problem is to display the list of title from firestore into a uipicker, I need to get data into an array like below:
[firsProgramme, secondProgramme, thirdProgramme]
I managed to display all the "title" from firestore in the string, not in the array
below is the code:
func getprogram() {
let db = Firestore.firestore()
db.collection("Programme").getDocuments()
{
(querySnapshot, err) in
if let err = err
{
print("Error getting documents: \(err)");
}
else
{
for document in querySnapshot!.documents {
let data = document.data()
let program = data["title"] as? String ?? ""
// let agencyId = document.documentID
print(program)
//print("\(document.documentID) => \(document.data())");
}
}
}
}
result print(program) return as below :
firstprogramme
secondprogramme
thirdprogramme
the other part for UIPicker is already being managed well.
Thanks in advance.
In you class create an array variable to hold information about your programs:
var programsArray: [String] = []
When reading data from Firebase, instead of print(program) use programsArray.append(program). Call UIPickerView reload function after you have all data.
DispatchQueue.main.async {
self.your_picker_view.reloadAllComponents()
}
And of course, use this array inside your pickerview datasource methods.