Firebase retrieve data below auto ID In Swift - ios

I'm in trouble in retrieving data from Firebase.
I'd like to read all contactName data in JSON under auto ID , then append to UIPickerView.
Here is my JSON tree (used childByAutoId())
And Here is my Swift Code
dbRef = Database.database().reference()
dbRef.child("user").child("contacts").queryOrdered(byChild: "contactName").observeSingleEvent(of: .value, with: {(snapshot) in
for snap in snapshot.children {
let userSnap = snap as! DataSnapshot
let contactName = userSnap.value as? String
self.pickOption.append("\(contactName)")
}
})
But the result shows me all nil data... looks like this.
How Can I fix it..?

I solved myself!
But first of all, I decided not to use UIPickerView.
And what I wanna do is to add data below auto ID.
I'm not sure this is good algorithm for solving this problem, But Anyway, I made it :)
dbRef.child("user/contacts/").observe(.value, with: {(snapshot) in
if let result = snapshot.children.allObjects as? [DataSnapshot] {
for child in result {
let orderID = child.key as String //get autoID
self.dbRef.child("user/contacts/\(orderID)/contactName").observe(.value, with: { (snapshot) in
if let nameDB = snapshot.value as? String {
if self.debtorName == nameDB {
self.dbRef.child("user/contacts/\(orderID)").updateChildValues(data)
}
}
})
}
}
})

Related

Swift, iOS: How do I extract data from my firebase database?

This is my firebase database.
I wish to go through my database to grab each ticket's value such as "ignore", "Peter rabbit....", "Incredibles 2....", etc.
Currently I am extracting data like this:
ref = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
ref?.child("users").child(uid!).observe(.childAdded, with: { (snapshot) in
if let userDict = snapshot.value as? [String:String] {
self.movieNameFromTickets.append(myValue)
}
})
But I feel that it isn't a good way to extract data because if I have another structure like tickets, it might print out the wrong information.
What would be a better way to extract my tickets' values?
Thanks :)
Try this :
Database
.database()
.reference()
.child("Users")
.child(Auth.auth().currentUser!.uid)
.child("Advertisements")
.queryOrderedByKey()
.observeSingleEvent(of: .value, with: { snapshot in
guard let dict = snapshot.value as? [String:Any] else {
print("Error")
return
}
// get value from dict here .
})

Fetch all user's first names in Firebase

I'm trying to retrieve all user's firstnames in my Firebase database. What is the best way to add them to an array?
Firebase database
-Users
-UserId1
- firstname: James
-UserId2
- firstname: Jennifer
Swift code
let rootRef = Database.database().reference()
let query = rootRef.child("Users").queryOrdered(byChild: "firstname")
query.observeSingleEvent(of: .value) {
(snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
let value = snapshot.value as? NSDictionary
let firstname = value?["firstname"] as? String ?? ""
print(firstname)
}
}
Might just be a typo ;) You should be using child inside your loop instead of snapshot. For instance, try replacing the following line:
let value = snapshot.value as? NSDictionary
with:
let value = child.value as? NSDictionary

Retrieving and Reading Data as NSArray from Firebase (Swift 3)

I'm working through a course on Udemy to build a chat app with Firebase, Backendless, and Swift. All of the issues (it was written for Swift 2 not 3) I've been able to resolve myself, but this one has me stumped. This function is supposed to retrieve data from the Firebase database, and apparently it was supposed to retrieve it as an NSArray, but it now retrieves it as an NSDictionary, which is making a huge list of errors in the other functions because it's not expecting a dictionary.
func loadRecents() {
firebase.childByAppendingPath("Recent").queryOrderedByChild("userId").queryEqualToValue(currentUser.objectId).observeEventType(.Value, withBlock: {
snapshot in
self.recents.removeAll()
if snapshot.exists() {
let sorted = (snapshot.value.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptior(key: "date", ascending: false)])
}
})
}
I've updated to Swift 3 as far as:
func loadRecents() {
ref = FIRDatabase.database().reference()
let userId = currentUser?.getProperty("username") as! String
ref.child("Recent").queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: {
snapshot in
self.recents.removeAll()
if snapshot.exists() {
let values = snapshot.value as! NSDictionary
}
})
}
Of course, using as! NSArray does not work. Would very much appreciate it if anyone can suggest a method to update this to use Swift 3, sort it by a value in the data, and be able to access it later on. Thanks!
func loadRecents() {
ref = FIRDatabase.database().reference()
let userId = currentUser?.getProperty("username") as! String
ref.child("Recent").queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: {
snapshot in
self.recents.removeAll()
if snapshot.exists() {
let values = snapshot.value as! [String:AnyObject]
}
})}
or you can use also let values = snapshot.value as! [Any]
Hope this will help you, try this code:
func loadRecents() {
let ref = FIRDatabase.database().reference()
let userId = currentUser?.getProperty("username") as! String
ref.child("Recent").queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: {
snapshot in
self.recents.removeAll()
guard let mySnapshot = snapshot.children.allObjects as? [FIRDataSnapshot] else { return }
for snap in mySnapshot {
if let userDictionary = snap.value as? [String: Any] {
print("This is userKey \(snap.key)")
print("This is userDictionary \(userDictionary)")
}
}
})
}

querying messages in firebase using swift [duplicate]

I have a Firebase resource that contains several objects and I would like to iterate over them using Swift.
What I expected to work is the following (according to the Firebase documentation)
https://www.firebase.com/docs/ios-api/Classes/FDataSnapshot.html#//api/name/children
var ref = Firebase(url:MY_FIREBASE_URL)
ref.observeSingleEventOfType(.Value, withBlock: { snapshot in
println(snapshot.childrenCount) // I got the expected number of items
for rest in snapshot.children { //ERROR: "NSEnumerator" does not have a member named "Generator"
println(rest.value)
}
})
So it seems there is a problem with Swift iterating over the NSEnumerator object returned by Firebase.
Help is really welcome.
If I read the documentation right, this is what you want:
var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value) { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
print(rest.value)
}
}
A better way might be:
var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value) { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? FIRDataSnapshot {
print(rest.value)
}
}
The first method requires the NSEnumerator to return an array of all of the objects which can then be enumerated in the usual way. The second method gets the objects one at a time from the NSEnumerator and is likely more efficient.
In either case, the objects being enumerated are FIRDataSnapshot objects, so you need the casts so that you can access the value property.
Using for-in loop:
Since writing the original answer back in Swift 1.2 days, the language has evolved. It is now possible to use a for in loop which works directly with enumerators along with case let to assign the type:
var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value) { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
for case let rest as FIRDataSnapshot in snapshot.children {
print(rest.value)
}
}
I have just converted the above answer to Swift 3:
ref = FIRDatabase.database().reference()
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
print(rest.value)
}
})
A better way might be:
ref = FIRDatabase.database().reference()
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? FIRDataSnapshot {
print(rest.value)
}
})
This is pretty readable and works fine:
var ref = Firebase(url:MY_FIREBASE_URL)
ref.childByAppendingPath("some-child").observeSingleEventOfType(
FEventType.Value, withBlock: { (snapshot) -> Void in
for child in snapshot.children {
let childSnapshot = snapshot.childSnapshotForPath(child.key)
let someValue = childSnapshot.value["key"] as! String
}
})
ref = FIRDatabase.database().reference().child("exampleUsernames")
ref.observeSingleEvent(of: .value, with: { snapshot in
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
guard let restDict = rest.value as? [String: Any] else { continue }
let username = restDict["username"] as? String
}
})
Firebase 4.0.1
Database.database().reference().child("key").observe(.value) { snapshot in
if let datas = snapshot.children.allObjects as? [DataSnapshot] {
let results = datas.flatMap({
($0.value as! [String: Any])["xxx"]
})
print(results)
}
}
Firebase 7.3.0
Database.database().reference().child("key").observe(.value) { snapshot in
if let datas = snapshot.children.allObjects as? [DataSnapshot] {
let results = datas.compactMap({
($0.value)
})
print(results)
}
}
If you have multiple keys/values, and want to return an array with dictionary elements, declare an array:
var yourArray = [[String: Any]]()
then change block body to this:
let children = snapshot.children
while let rest = children.nextObject() as? DataSnapshot, let value = rest.value {
self.yourArray.append(value as! [String: Any])
}

Iterate over snapshot children in Firebase

I have a Firebase resource that contains several objects and I would like to iterate over them using Swift.
What I expected to work is the following (according to the Firebase documentation)
https://www.firebase.com/docs/ios-api/Classes/FDataSnapshot.html#//api/name/children
var ref = Firebase(url:MY_FIREBASE_URL)
ref.observeSingleEventOfType(.Value, withBlock: { snapshot in
println(snapshot.childrenCount) // I got the expected number of items
for rest in snapshot.children { //ERROR: "NSEnumerator" does not have a member named "Generator"
println(rest.value)
}
})
So it seems there is a problem with Swift iterating over the NSEnumerator object returned by Firebase.
Help is really welcome.
If I read the documentation right, this is what you want:
var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value) { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
print(rest.value)
}
}
A better way might be:
var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value) { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? FIRDataSnapshot {
print(rest.value)
}
}
The first method requires the NSEnumerator to return an array of all of the objects which can then be enumerated in the usual way. The second method gets the objects one at a time from the NSEnumerator and is likely more efficient.
In either case, the objects being enumerated are FIRDataSnapshot objects, so you need the casts so that you can access the value property.
Using for-in loop:
Since writing the original answer back in Swift 1.2 days, the language has evolved. It is now possible to use a for in loop which works directly with enumerators along with case let to assign the type:
var ref = Firebase(url: MY_FIREBASE_URL)
ref.observeSingleEvent(of: .value) { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
for case let rest as FIRDataSnapshot in snapshot.children {
print(rest.value)
}
}
I have just converted the above answer to Swift 3:
ref = FIRDatabase.database().reference()
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
print(rest.value)
}
})
A better way might be:
ref = FIRDatabase.database().reference()
ref.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot.childrenCount) // I got the expected number of items
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? FIRDataSnapshot {
print(rest.value)
}
})
This is pretty readable and works fine:
var ref = Firebase(url:MY_FIREBASE_URL)
ref.childByAppendingPath("some-child").observeSingleEventOfType(
FEventType.Value, withBlock: { (snapshot) -> Void in
for child in snapshot.children {
let childSnapshot = snapshot.childSnapshotForPath(child.key)
let someValue = childSnapshot.value["key"] as! String
}
})
ref = FIRDatabase.database().reference().child("exampleUsernames")
ref.observeSingleEvent(of: .value, with: { snapshot in
for rest in snapshot.children.allObjects as! [FIRDataSnapshot] {
guard let restDict = rest.value as? [String: Any] else { continue }
let username = restDict["username"] as? String
}
})
Firebase 4.0.1
Database.database().reference().child("key").observe(.value) { snapshot in
if let datas = snapshot.children.allObjects as? [DataSnapshot] {
let results = datas.flatMap({
($0.value as! [String: Any])["xxx"]
})
print(results)
}
}
Firebase 7.3.0
Database.database().reference().child("key").observe(.value) { snapshot in
if let datas = snapshot.children.allObjects as? [DataSnapshot] {
let results = datas.compactMap({
($0.value)
})
print(results)
}
}
If you have multiple keys/values, and want to return an array with dictionary elements, declare an array:
var yourArray = [[String: Any]]()
then change block body to this:
let children = snapshot.children
while let rest = children.nextObject() as? DataSnapshot, let value = rest.value {
self.yourArray.append(value as! [String: Any])
}

Resources