Reading Firebase child by auto ID swift
Here's the code to read the Firebase structure proposed in the question
let planitsRef = self.ref.child("planits")
planitsRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let planSnap = child as! DataSnapshot
let planDict = planSnap.value as! [String: Any]
let title = planDict["plan_title"] as! String
let senderId = planDict["sender_id"] as! String
print("plan title: \(title) senderId: \(senderId)")
let peopleOnPlanitSnap = planSnap.childSnapshot(forPath: "people_on_planit")
for peopleChild in peopleOnPlanitSnap.children {
let peopleChildSnap = peopleChild as! DataSnapshot
let userSnapDict = peopleChildSnap.value as! [String: Any]
let userId = userSnapDict["user_id"] as! String
print(" userId: \(userId)")
}
}
})
and the output
plan title: Some title senderId: 39FdLfdIO8832
userId: uid_0
userId: uid_1
-- A couple of notes --
Since the associated users appear to be stored by their user Id and that's the only data stored within that node, you may want to change this node
people_on_planit
-LEmh6IxqguVBJEwghZv (auto ID)
userID: "kkdiEW0D9"
to look like this
people_on_planit
uid_x: true //uid_x would be kkdiEW0D9 etc
uid_y: true
it's a bit shallower and cleaner and requires less code to read it. Also, you can query it more easily if that ever comes up.
also note that I changed the naming convention slightly; you are welcome to format keys however you want but I went with keys like plan_title instead of PlanIt Title and sender_id and user_id instead of senderId and userId. My practice is for actual firebase keys I use all lowercase, underscore instead of spaces, and in code, I use lower/uppercase with no spaces. So if you copy paste my code, you'll need to change those.
How can I access Firebase data under a childByAutoID?
Here we go. An answer to the question. However, and I mentioned in my comment to the question, the structure could be improved. However, there may be more children under each listing child so this answer handles it.
This just print's each authors name but it shows how to get to it so the answer should be expanded for the other child nodes.
let listingsRef = self.ref.child("listings")
listingsRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let autoIdSnap = child as! DataSnapshot
for autoChild in autoIdSnap.children {
let childSnap = autoChild as! DataSnapshot
let dict = childSnap.value as! [String: Any]
let author = dict["author"] as! String
print(author)
}
}
})
Oh, and a better structure may be
listings
childByAutoId
author: "Some author"
listing: 9780184888
childByAutoId
author: "Another author"
listing: 9799292598
Edit: If there will only ever be one and only one childByAutoId under each listing, you can eliminate the loop in the above and do this
let listingsRef = self.ref.child("listings")
listingsRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let autoIdSnap = child as! DataSnapshot //each listing
let childDict = autoIdSnap.value as! [String: Any] //a dict of items within the listing
let firstKey = childDict.keys.first! //the key to the first item
let valuesDict = childDict[firstKey] as! [String: Any] //the values for that key
let author = valuesDict["author"] as! String //the author value
print(author)
}
})
Reading Data stored via Autoid from Firebase Swift
The way I usually do this is by:
ref.child("Phrases").observeSingleEvent(of: .value, with: { snapshot in
let value = snapshot.value as! [String:Any]
let name = value["phrase"] as? String ?? ""
})
Alternatively you could unwrap it first
ref.child("Phrases").observeSingleEvent(of: .value, with: { snapshot in
if let value = snapshot.value as? [String:Any] {
let name = value["phrase"] as? String ?? ""
}
})
Firebase: Accessing Data Stored via childByAutoID
I have the answer. To access the key of the randomly generated autoId, you have to pass it as a FIRDataSnapShot.
for snap in snapshot.children.allObjects {
let id = snap as! FIRDataSnapshot
print(id.key)
}
This will give you the randomly generated keys.
Accessing Firebase Data inside unique AutoID
The issue you're having is that you're trying to dig deeper but can't as you don't have a hold of that id. You'll want to use the .childAdded
in your reference observation when you want to get inside of a list in your JSON tree when you don't have a hold of that id to get inside - this will be called as many times as there are values inside of Category 1 tree:
let reference = Database.database().reference()
reference.child("Category 1").child("optionSelected").observe(.childAdded, with: { (snapshot) in
let uniqueKey = snapshot.key // IF YOU WANT ACCESS TO THAT UNIQUE ID
print(uniqueKey)
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let date = dictionary["date"] as? String
let variableOne = dictionary["Variable 1 Float"] as? Float
let variableOne = dictionary["Variable 2 Float"] as? Float
}, withCancel: nil)
You may also want to avoid using spaces in your database keys to avoid any problems in the near future. I'd stick with the common lowercased underscore practice e.g. "category_1" or "variable_2_float"
Retrieve randomly generated child ID from Firebase
tasksRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
for task in snapshot.children {
guard let taskSnapshot = task as? FDataSnapshot else {
continue
}
let id = task.key
// do other things
}
}
iOS: How to get and shuffle autoID data of users stored in childnode of firebase?
There are several questions within the question so let's address one.
How to select a random node from Firebase Realtime Database. Well, you don't do it with the Firebase API as Firebase doesn't offer that functionality. However, you can still do it.
First lets start with a typical users node
users
uid_0
name: "Frank"
uid_1
name: "Leroy"
uid_2
name: "Henry"
uid_3
name: "Fred"
So if that's the users node, you can use it for this solution. However, many users node have a lot of other data stored in them - and to select a random node we don't care about that data. What we do is create another node that contains only the node keys - this will keep is pretty small, even if there are thousands of users
user_keys
uid_0: true
uid_1: true
uid_2: true
uid_3: true
Then, to select a random node, we load in all of the user keys using .value, iterate over them to load the keys into an array, then a Swift 4 random number generator to select some keys which we load into another array.
Then we iterate over that array to grab the actual user nodes from Firebase. We also don't want duplicates so as we select nodes from the array, we remove those nodes so they are not selected again. Here's a function to select 3 random nodes, retrieve the users data and print the users name.
func getThreeRandomNodesAndPrintUserName() {
var myKeyArray = [String]()
let ref = self.ref.child("user_keys")
//retreives all nodes in the user_keys node
ref.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children { //build the array of keys
let snap = child as! DataSnapshot
let key = snap.key
myKeyArray.append(key)
}
var randomKeyArray = [String]()
for _ in 0...2 { //will iterate three times
let count = myKeyArray.count //get the number of elements
let randomInt = Int.random(in: 0..<count) //get a random index for the array
let randomUserKey = myKeyArray[randomInt]
randomKeyArray.append(randomUserKey)
myKeyArray.remove(at: randomInt) //remove that object so it's not selected again
}
let numberOfKeys = randomKeyArray.count
for i in 0..<numberOfKeys {
let thisUserKey = randomKeyArray[i]
let userRef = self.ref.child("users").child(thisUserKey)
userRef.observeSingleEvent(of: .value, with: { snapshot in
let name = snapshot.childSnapshot(forPath: "name").value as! String
print(name)
})
}
})
}
and then just a call to that function will print three random users names
self.getThreeRandomNodesAndPrintUserName()
and the output for first run
Fred
Frank
Henry
and then the second run
Henry
Leroy
Fred
etc
How can I delete a specific child node in Firebase from UITableViewCell using Swift
Following on from what MHDev has already answered:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
if let exerciseName = exercises[indexPath.row].exerciseName {
let ref = FIRDatabase.database().reference().child("userExercises")
ref.queryOrdered(byChild: "exerciseName").queryEqual(toValue: exerciseName).observe(.childAdded, with: { (snapshot) in
snapshot.ref.removeValue(completionBlock: { (error, reference) in
if error != nil {
print("There has been an error:\(error)")
}
})
})
}
exercises.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .left)
}
}
How to get the key from the value in firebase
That's because you're using a ValueEventListener
. If the query matches multiple children, it returns a list of all those children. Even if there's only a single matches child, it's still a list of one. And since you're calling getKey()
on that list, you get the key of the location where you ran the query.
To get the key of the matches children, loop over the children of the snapshot:
mDatabase.child("clubs")
.orderByChild("name")
.equalTo("efg")
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String clubkey = childSnapshot.getKey();
But note that if you assume that the club name is unique, you might as well store the clubs under their name and access the correct one without a query:
mDatabase.child("clubs")
.child("efg")
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String clubkey = dataSnapshot.getKey(); // will be efg
Related Topics
Alamofireimage How to Clean Memory and Cache
Hiding Dividers in Nssplitview
Node.Physicsbody.Joints Downcasting Error
How to Properly Test Against Certain Values in Nseventmodifierflags via Swift
Swiftui: Problem with Adding a Property to Data Struct
How to Store the Progress of Progressview into Arraylist as One Element
Getting Wrong Date from Dateformat
Inserting Data into Realm Db with Progress
Cannot Use Unarchivefromfile to Set Gamescene in Spritekit
How to Stop Tokbox Screen Sharing in Swift
Swift How to Design Uiwebview Auto Resize Full Screen in Story Board
Uicollectionviewcell Not Forcing Cell Size
Testing If Double from Textfield Has a Value or Not
Macos Playground: How Can Change the Background Color