Firebase how to store/get array of users efficiently - swift

I have a dynamic list/array of users that I want to add to my firebase db. I looked at Setting arrays in Firebase using Firebase console which suggested to store arrays like the following data structure:
uid: {
attendees: {
"Bill Gates": true,
"Larry Page": true,
"James Tamplin": true
}
}
However, creating a dictionary and adding them one by one to the user field is inefficient:
let dict: Dictionary<String, Any> = [
"location": "",
"attendees": {
"Bill Gates": true,
"Larry Page": true,
"James Tamplin": true,
....
}
]
If I have 100 attendees, it's inefficient to add them one by one to my dictionary and set each of its value to true. How can I add my data more compactly? When I get back the user dictionary, how can I retrieve each key in attendees?

I am not sure what will be the more efficient way of setting up a list of attendees with true or false indicating if they are joining the program or not. In any way, you will have to set the data of their availability one by one after you're getting it from somewhere else.
I think you can create a dictionary with your attendees and their availability and push the dictionary altogether with a single firebase operation. Once you are done with preparing the dictionary that you want to push you can consider saving the values in your firebase database as follows.
databaseRef.child("events").child(someKey).updateChildValues(attendeesDictionary)

Related

add a map inside map and retrieve it from Firestore - Flutter

The scenario is, am trying to record a history of the challenges that user have participated in, the history only takes name, date, and isWin information from the challenge which will be showed later on "my Challenges" page for each user.
after a while thinking on how to solve this problem i came up with the logic of adding a map to the user model called challengesHistory, inside this map the information of each challenge that user participated in will be stored as another map inside the big map so it will become something like this:
Map challengeHistory = {
"challenge-1": {"name": "", "date": "", "isWin": ""}
}
i have added the map to the user model correctly, now my problem is how to add new map each time user clicks on "participate" so it becomes:
Map challengeHistory = {
"challenge-1": {"name": "", "date": "", "isWin": ""}
"challenge-2": {"name": "", "date": "", "isWin": ""}
}
and each time user participate in a challenge it adds challenge-4 ,5 ,6 ... and so on
code of the button when user clicks on "participate":
FirebaseFirestore.instance.collection("Users").doc(user!.uid).update({
'points': loggedInUser.points! + 3,
'challenges': loggedInUser.challenges! + 1,
'challengeMember': FieldValue.arrayUnion([widget._challengeName]),});
so using this code how can i add a new map inside "challengeHistory" map.
my second question is if i want to retrieve an information like the name of the fourth challenge how can i do that.
last thing how to iterate the whole "challengeHistory" map and print each challenge information.
i would be thankful for help.
Try make challengeHistory a List<Map> so you can simply call challengeHistory.add() to add other challenges (Map).
Then you can also call challengeHistory[3]["name"] to get for example the name of the fourth challenge.
You can also loop through each challenge inside of the list:
for(var c in challengeHistory)
{
print(c["name"]);
print(c["date"]);
print(c["isWin"]);
}

Swift Checklist - Saving the Switch Data for multiple Rows

So I have a Simple UITableView that will display a UILabel and a UISwitch. I need to be able to get the values of each switch update my object then eventually send the data the API. I has a semi working concept. But this only worked if ALL the cells were visible. Before I only had 5 items to be checked. So I could simply loop through everything and get the data. Now my checklist has grown to over 20 items.
I understand to a degree why the current code doesn't work. It finds nil values. That would be the cells that aren't visible.
My big question is how do i go about capturing the value of all the cells and the value of all the UISwitch values and update my object?
I tried to use the KVO method. This is what I have so far, I have never used this before and a bit lost:
private var observation: NSKeyValueObservation?
observation = switchCell.observe(\.switchOne, options: [.old, .new]) { value, change in
print("value: \(value.switchOne.isOn)")
print("change old: \(change.oldValue)")
print("change new: \(change.newValue)")
}
My issue is I am not sure what I am supposed to use for the key path. Iget the following warning:
Passing reference to non-'#objc dynamic' property 'switchOne' to KVO method 'observe(_:options:changeHandler:)' may lead to unexpected behavior or runtime trap
Then the simulator doesn't boot up. What is the easiest way/best way to do this? Like I said I have 2)+ items on my checklist as I completed each item, I turn the switch on. Then I need to get the value for each item, and update the object with the correct value. Then I send the data to the API to store the info to the database. From what I was reading this seemed to be the right direction.
store predefined status of switches in array of dictionary like:
let alreadyYouHaveThis = [["id": 1, "title": "name"...., ], [ "id": 1, "title": "name"....., ],["id": 1, "title": "name"...., ]
just add one more key in the same data like status...
let updatedData = [["status": true, "id": 1, "title": "name"...., ], ["status": true, "id": 1, "title": "name"....., ],["status": false, "id": 1, "title": "name"...., ]
now that status will be used in cellforindexpath method as other:
func cellforindexpath() ..... {
let status = data[indexPath.item]["status"]
swithc.tag = indexpath.item
setswitchstatus on above value
}
and action for switch :
#Objc func switchStatus(_ switch: UISwitch) {
let status = data[switch.tag]
status != status
data[switch.tag]["status"] = status
....
}
or can edit main data source and add these status in that data.
if you cant perform this let me know.

How to store data in Firestore (Swift)

I have an iOS app using Cloud Firestore and have problems with updating the data. My goal is to add urls to a dictionary one by one, but all I get is rewritten one value. How should I use setData and updateData? Tried it different ways
storageRef.child("users/" + currentUser.value!.documentID + "/" + faceRef.documentID + ".jpg")
.putData(data!).observe(.success) { (snapshot) in
guard let downloadURL = snapshot.metadata?.downloadURL()?.absoluteString else { return }
let db = self.fsReference.document(self.currentUser.value!.documentID)
var dict = ["faces": ["": ""]]
dict["faces"] = ["newvalue\(downloadURL.hashValue)": downloadURL]
db.updateData(dict)
completion?()
Here's what I tried. Any advice would be nice, thanks in advance!
UPD: Tried to move my dictionary to subcollection, but after .collection("newCollection").document("newdocument") collection does not appear. What might be the problem?
So what I am seeing is you are using cloud storage to save profile pictures and you want to save each one of the urls those pictures. You need to understand that both setValue() and updateValue() do just about the same thing. A note with updateValue() is it will create that document if it doesn't already exist. So, when updating values in Firestore understand that it sets the value to what you give it, which can be misleading at first.
1st When updating any document start by getting the document first. If people are constantly updating different document you may want to consider using Firestore transactions: https://firebase.google.com/docs/firestore/manage-data/transactions#transactions
This will make sure that your data is updated correctly.
2nd Append the URL to the to the array, I am not how you set it up, but I would setup the firestore to look something like this
"users" = [
"unique_id = "{
"firstname": "John",
"lastname": "Doe",
"unique_id": "document_id_here"
"faces": [ {key: value} ]
}
]
When you serialize that object your faces object should be this [[String: Any]]
3rd, last step would be to get the document and update just that value
// Get the value in the completion with the data use this code
// Drill down to the property you want to update using the completion data ex.
var faces = completedData.faces
faces.append("[key: value]")
// Update the data back to firestore
let path = Firestore.firestore().collection("users").document("unique_user_id")
// Merging is so important. otherwise it will override your document
path.setData(["facesKey: faces"], merge: true) {(error in
if let error = error {
// good error handling here
}
// Successfully updated document
)}

How to store only values of fields into the state in Antd forms

I have crated a basic antd controled form synchronized with my state in Redux store, when fields changes are transmited to my store via the onFieldsChange method i get an object with some unwanted propretys in my state.
For the code you can take the one provided in the official documentation
Store Form Data into Upper Component
the received object is like one below :
{
"username": {
"value": "test",
"name": "username",
"touched": true,
"dirty": false,
"validating": false
}
}
I want to keep my state clean and store only the value, in my state, are these other properties needed or can be recreated like as in the initial load ?

How do I retrieve a key from a firestore document (using swift 4/ios)

In the firebase docs for firebase database there is info on flattening a database and a message app is used as an example.
https://firebase.google.com/docs/database/web/structure-data
// Conversation members are easily accessible
// and stored by chat conversation ID
"members": {
// we'll talk about indices like this below
"one": {
"ghopper": true,
"alovelace": true,
"eclarke": true
},
"two": { ... },
"three": { ... }
},
Under "members"/"one" each key is the name of a participating member in the chat. I'm pretty sure in firebase database there is a getKey method to get each key.
I have set up my database (using firestore instead of firebase) in a similar way but where each chat is a unique identifier and the document contains the members of the chat where the key is their firebase auth id eg.
var docsref: DocumentReference?
docsref = self.defaultStore?.colleection("chats").document(chatID)
docsref?.getDocument { (document, error) in
if let _ = document {
print("document!.data()")
} else {
print("Document does not exist")
}
}
And when I output:
print(document!.data())
I get ["2mHuccccxxxxxxxxxxk4wkIAt33": 1] which is the firebase auth code of one of the participating chat members and a boolean.
I would like to get that key but wasn't sure how.
Thanks.
I'm not sure if it's the exact Syntax but self.defaultStore?.colleection might be a typo with the double E. It could also possibly be that you're missing a step. You're getting inside the chatID and you're expecting to output the keys inside members without actually accessing it. I'd access members after .document(chatID)
You can get it as follows.
to get value document.data()
to get key document.documentID