Is is possible to store a Firestore field into a Swift file, and use the Swift file in a TableViewController? - swift

Is it possible to extract a Firestore field (from a document), store it in a Swift file, and then use the value to create cells in a TableViewController?
The following is stored in my Firestore database:
users {
userid {
"level":0
"subjects":[""]
}
}
Can I somehow store 'subjects' into a Swift file (blank), and use this variable to make Table View cells (using rows)?

If what you are trying to do is query users for a specific user's "subjects" and store it in an array then this should work.
var db = Firestore.firestore()
let usersRef = db.collection("users").document(userid)
usersRef.getDocument { (document, error) in
if let document = document, document.exists {
let subjects = document.data()!["subjects"]
} else {
print("Document does not exist")
}
}
That subjects array can be used for your table view.

Related

How can I reference second level collections in Firebase?

Currently my Firebase database is using the following structure
Users
User 1 Data
User 2 Data...
However I have created a new collection inside of the "users" collection called "products" which will store product details that users have uploaded on the application.
How can I ensure that once a user uploads a new product, it is only uploaded into their 'User X data' dataset, inside the respective "products" collection. The code I currently have only uploads the data into the "users" collection, with no reference of the users who added the product as required. I have shown the structure of my Firebase database below for reference.
Here is my code:
let user = Auth.auth().currentUser
db.collection("users").getDocuments { (snapshot, error) in
if let error = error {
print(error)
return
} else {
for document in snapshot!.documents {
let data = document.data()
let userId = data["uid"] as! String
if userId == user?.uid {
db.collection("users").document("products").setData(["productNameField":firstName, "productURLField":lastName,"productPriceField":ebayName, "productDescriptionField":etsyName, "productTimeRemainingField":email])
}
}
}
}
How would I go about updating my code to achieve this?
I think you're looking for
let user = Auth.auth().currentUser
db.collection("users").getDocuments { (snapshot, error) in
if let error = error {
print(error)
return
} else {
for document in snapshot!.documents {
let data = document.data()
let userId = data["uid"] as! String
if userId == user?.uid {
document.reference.collection("products").addDocument(["productNameField":firstName, "productURLField":lastName,"productPriceField":ebayName, "productDescriptionField":etsyName, "productTimeRemainingField":email])
}
}
}
}
So here document is the DocumentSnapshot that you're looping over, so document.reference gives you the reference to that specific document, and document.reference.collection("products") then points to the `products subcollection for that specific document.
You're wastefully looping over the entire list of users to FIND the user document needed. Simplify, simplify - use the user.uid as the Id of the user document!! (i.e. when you create the user document, save it as
db.collection("users").doc(user.uid).set({whatever})
...then it's trivial to access as...
let user = Auth.auth().currentUser
db
.collection("users")
.doc(user.uid)
.collection("products")
.setData([
"productNameField":firstName,
"productURLField":lastName,
"productPriceField":ebayName,
"productDescriptionField":etsyName,
"productTimeRemainingField":email
]);
If there is another reason to keep the docID and the uid separate (not shown here), then use a query to get the SPECIFIC document with the uid, rather than downloading ALL of them
let user = Auth.auth().currentUser
db
.collection("users")
.where(field: "uid", opStr:"==", value: user.uid)
.getDocuments( { (snapshot, error) in
if let error = error {
print(error)
return
} else { //the query should only return the one document, but queries always return an array
snapshot
.documents[0]
.ref()
.document("products")
.setData([
"productNameField":firstName,
"productURLField":lastName,
"productPriceField":ebayName,
"productDescriptionField":etsyName,
"productTimeRemainingField":email
])
}
}
...etc...
I don't generally use Swift, so the where clause may require different formatting, but the idea is GET ONLY THE DOCUMENT YOU NEED. Your security rules should only be allowing this, anyway.

How to get the field values in firebase cloud database?

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]

Firebase firestore getting data from inside collection

Is there a way to grab the data from owner ID I'm not able to access the collection oath because the documentID is auto-generated and not a specific value I have control of
A possible option would be to query your documents and retrieve a specifc OwnerID like this.
If you want to fetch all OwnerIDs from all of your documents just remove the 'whereField'.
Also check out the Firebase documentation for queries.
let docRef = db.collection("YOURCOLLECTIONNAME")
let query = docRef.whereField("OwnerID", isEqualTo:"VAL")
query.getDocuments{ (querySnapshot, error) in
if let error = error {
print("\(error.localizedDescription)")
}else {
for documents in (querySnapshot?.documents)! {
if let owner = documents.get("OWnerID") as? String {
print(owner)
}
}

How can I create a snapshot to listen to users being ADDED to my Firestore database?

I am using Firestore. I am trying to listen for when a new user is added. The problem is, each user also has a friends dictionary. So when I use a snapshot, my code is detecting both events of (1) A new user being added and (2) a new friend being added.
I have tries iterating over the document changes data and restricting doc.document.data()["friends"] == nil. Why isn't this working/how can I properly add a restriction to only include when a new user is added?
func observeUsers(onSuccess: #escaping(UserCompletion)) {
Ref().firestoreUserRef.collection("users").addSnapshotListener { (querySnapshot, error) in
if error != nil {
print("error with observeUser snapshot")
return
}
querySnapshot?.documentChanges.forEach { doc in
//I want to detect that a new user was added, I do not want to detect if a friend was added
if (doc.type == .added) && doc.document.data()["friends"] == nil {
guard let dict = querySnapshot else { return }
for document in dict.documents {
var dictionary = [String : Any]()
dictionary = document.data()
if let user = User.transformUser(dict: dictionary) {
onSuccess(user)
}
}
}
}
}
}
The easiest way is starting from the data model to support the types of queries you want. In this case, when you create a new user (which I assume always has no friends), set the friends field explicitly to null. This will let you query for all new users:
Ref().firestoreUserRef.collection("users").whereField("friends", isEqualTo: NSNull()).addSnapshotListener ...
An assumption here is your transformUser process will update the document and replace null with either a list of friends of an empty array so that it no longer matches the query.

Display Firestore data into UIPicker Swift 4

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.