How can I read the value of a Firebase database dictionnary created using .childByAutoId() in Swift? - swift

I have a dictionary of dictionary of Strings stored in a Firebase database. It can be seen below.
As you can see, each entry is created using .childByAutoId() and contains two variables: text and tag.
I wish to be able to go through all of the entries, and compare the value of text with a variable saved locally in my app. I have tried many ways, but cannot find any solution that works. How should I proceed?
Thank you in advance for your help.

You need to observe database at specific reference and then convert a snapshot that will be send to you. The snapshot represents a fragment of your database at given path
let dbRef = Database.database().reference().child("messages")
dbRef.observeSingleEvent(of: .value) { (snapshot) in
for message in snapshot.children{
let msg = (message as! DataSnapshot).value //message as snapshot
//now you need to cast it to your structure([String:String])
let projectObj = Message(snapshotChild: msg as! [String:String])
//and do your comparison
}
}

Related

Retrieve child entry from Firebase Realtime Database without []. - Swift 5

I'm a little stuck with something small but that is giving me some headaches! I have a Realtime Database and I am able to retrieve the information I need from it. My only problem is that instead of printing for example (ex.: 200) is printing (ex.: [200])!
This is my code:
func readData() {
FirebaseDatabase.Database.database().reference().child("Available_Funds").observeSingleEvent(of: .value, with: { snapshot in
guard let value = snapshot.value as? [String: Any] else {
return
}
let amountWallet = value.values
print(amountWallet)
self.currentBalanceLabel.text = "$" + "\(amountWallet)"
print("\(value)")
})
}
Right now what I get printed with this code is $[200] for example, instead of just $200, which is what I intend to get.
Tried looking online, but no luck with this! Does someone know how to remove these square brackets from printing?
values is an Array -- thus the []. When you say value.values, you're asking for all of the values of the key/value pairs in snapshot.value.
If you intend to get a single value from it, you would use amountWallet[0] to get the first element. Keep in mind that this will crash if amountWallet has 0 elements (arrays are zero indexed).
amountWallet.first will give you an Optional that will be safe to use, but you would need to unwrap it for printing:
let amountWallet = value.values
if let singleAmount = amountWallet.first {
print(singleAmount)
self.currentBalanceLabel.text = "$" + "\(singleAmount)"
}
You're calling it back as an array of strings [String: Any]
You can either change this (remove []) or access the first element in the array: amountWallet[0].

Firebase Checking If Username is Taken [duplicate]

Okay I am reading from a database and when I print the individual variables they print out correctly. However it seems like the data refuses to append to the array. Anyone know why? I can't figure it out at all.
let commuteBuilder = Commutes()
Database.database().reference().child("Users").child(user).child("Trips").observe(DataEventType.childAdded, with: { (snapshot) in
//print(snapshot)
if let dict = snapshot.value as? NSDictionary {
commuteBuilder.distance = dict["Distance"] as! Double
commuteBuilder.title = dict["TripName"] as! String
commuteBuilder.transportType = (dict["Transport"] as? String)!
}
commuteArray.append(commuteBuilder)
})
print("helper")
print(commuteArray.count)
return commuteArray
The data is correctly added to the array, just not at the time that you print the array's contents.
If you change the code like this, you can see this:
let commuteBuilder = Commutes()
Database.database().reference().child("Users").child(user).child("Trips").observe(DataEventType.childAdded, with: { (snapshot) in
if let dict = snapshot.value as? NSDictionary {
commuteBuilder.distance = dict["Distance"] as! Double
commuteBuilder.title = dict["TripName"] as! String
commuteBuilder.transportType = (dict["Transport"] as? String)!
}
commuteArray.append(commuteBuilder)
print("added one, now have \(commuteArray.count)")
})
print("returning \(commuteArray.count)")
return commuteArray
You'll see it print something like this:
returning 0
added one, now have 1
added one, now have 2
etc.
This is likely not the output you expected. But it is working as intended. Firebase loads data from its database asynchronously. Instead of blocking your code, it lets the thread continue (so the user can continue using the app) and instead calls back to the code block you passed to observe when new data is available.
This means that by the time this code returns the array it is still empty, but it later adds items as they come in. This means that you cannot return data from a function in the way you are trying.
I find it easiest to change my way of thinking about code. Instead of "First get the data, then print it", I frame it as "Start getting the data. When data comes back, print it".
In the code above, I did this by moving the code that prints the count into the callback block. Instead of doing this, you can also create your own callback, which is called a completion handler or closure in Swift. You can find examples in this article, this article, this question Callback function syntax in Swift or of course in Apple's documentation.

Store every username in the firebase database into an array variable?

Im trying to build a social media app and I have the design down and Ive been up all night trying to figure this out with no luck. I'm fairly new to coding so any help would be appreciated! Thank You! (Also my apologies if this question is already asked. Ive tried looking everywhere and couldn't find anything)
Well to start off you need to create variable which will be database reference and array where the data will be stored such as:
var Array = [String]() //array of strings (usernames)
var ref : DatabaseReference! //define type of variable
then you assign it in viewDidLoad:
ref = Database.database().reference()
using this you'll be able to access your database and load current users:
ref.child("data").observeSingleEvent(of: .value, with: { (snapshot) in
guard let value = snapshot.value as? NSDictionary else {
self.listIsEmpty()
print("The user has no data in the database")
return
}
let userItem = value["Username"] as? [String] //loads the data
self.Array = userItem! //saves data to array
and then finally to write data you start by appending array which we have:
Array.append(textField.text) //reference textfield where username is or variable
ref.child("data").setValue(["Username":self.Array])

Value not being removed from dictionary

I have a dictionary in Firebase called peopleWhoLike, the key is an auto-id and the value is the uid of the user who liked, I'm trying to loop through the peopleWhoLike dictionary and find the entry with the current users uid as the value so that I can remove it, but the value is not being removed.
func removeLike(postID: String){
ref.child("posts").child(postID).observe(.value, with: { (snapshot) in
if let info = snapshot.value as? [String : AnyObject]{
if var peopleWhoLike = info["peopleWhoLike"] as? [String : String]{
print("peopleWhoLike - \(peopleWhoLike)")
for person in peopleWhoLike{
if person.value == FIRAuth.auth()!.currentUser!.uid{
peopleWhoLike.removeValue(forKey: person.key)
print("personkey - \(person.key)")
}
}
}
}
})
}
Both print statements print correctly, ie person.key being the correct key
Any help would be much appreciated thanks!
you have only an snapshot (a copy) of the data there
to remove the value from the firebase database;
try this:
//path should be like this (i guess):
let currentUserUid = FIRAuth.auth()!.c‌​urrentUser!.uid
ref.child("posts")
.child(postId)
.child("peopleWhoLike")
.chi‌​ld(currentUserUid)
.rem‌​oveValue()
or same:
let currentUserUid = FIRAuth.auth()!.c‌​urrentUser!.uid
ref.child("posts/\(postId)/peopleWhoLike/\(currentUserUid)").rem‌​oveValue()
UPDATE
you you like to remove the person key - then you can:
a) iterate over peopleWhoLike and find if it is the user ( but please put this let currentUserUid = FIRAuth.auth()!.c‌​urrentUser!.uid outside the loop!
//path should be like this (i guess):
let currentUserUid = FIRAuth.auth()!.c‌​urrentUser!.uid
// loop and when match `person.value == currentUserUid` then:
ref.child("posts")
.child(postId)
.child("peopleWhoLike")
.chi‌​ld(person.key) //<-- change here
.rem‌​oveValue()
b) you search in the query. and remove then the resulting node.
ref.child("posts")
.child(postId)
.child("peopleWhoLike")
.startAt(currentUserId)
.endAt(currentUserId)
. [...] do something
i dont know if you can direct call .removeValue() at this point. but with a SingleEvent and an snapshot you can do snapshot.ref.removeValue() - doublecheck before you delete. but since this results in a reference you should direct able to call .removeValue()
ref.child("posts")
.child(postId)
.child("peopleWhoLike")
.startAt(currentUserId)
.endAt(currentUserId)
.removeValue()
note: this search takes longer than a direct path
see here doc for query:
https://firebase.googleblog.com/2013/10/queries-part-1-common-sql-queries.html#byemail
https://firebase.google.com/docs/database/ios/read-and-write#delete_data
NOTE:
i would advice you to save it with the userUid as key because you only need a onliner to delete (see my first codesnippet where you not need to get all data from peopleWhoLike) and as value just 1 or you can save the current date (then you know when it was liked)

Retrieving Data from FireBase SWIFT

I'm trying to get data out of a firebase database if the addedByUser = a value stored in the application.
With what I currently have, nothing is appearing in the table.
The firebase database looks like this:
workout1
"name"
"addedByUser"
My code looks like this:
workout3Ref.observeEventType(.Value, withBlock: { snapshot in
var newWorkout = [Workout1Info]()
for item in snapshot.children {
let createdBy = snapshot.value["addedByUser"] as? String
if createdBy == Username.sharedInstance.userDetail {
let workoutItem = Workout1Info(snapshot: item as! FDataSnapshot)
newWorkout.append(workoutItem)
}
}
self.workouts = newWorkout
self.tableView.reloadData()
})
When I get data normally without comparing if the addedByUser it normally works. Does anyone know why it isn't working?
Thanks for the help
Here's my guess based on a super vague question with some coding issues:
The createdBy is the users name or uid as a string.
The Username.sharedInstance.userDetail is an object (of some kind)
So you are comparing a String to an object that isn't a string, and that won't work.
Also, if the node you are query-ing is the /workout1 node, then you should probably name your reference workout1Ref instead of workout3Ref. That may help keep things straight in code.
While you are comaparing String createdBy with Username.sharedInstance.userDetail check your property Username.sharedInstance.userDetail also should be of String type.