Firebase Get Child Id Swift iOS

Firebase get child ID swift ios

It is hard to tell from your question exactly what you are doing, but does this get you the list you need?

databaseRef.child("Active_Orders").observeEventOfType(.Value, withBlock: { (snapshot) in 
if let result = snapshot.children.allObjects as? [FIRDataSnapshot] {
for child in result {
var orderID = child.key as! String
print(orderID)
}
}
})

I believe this block should iterate over all the children that are inside "Active_Orders" and print out their key value (which seems to be what you are trying to print).

Get current child ID from Firebase using UITableViewController

You will have to query firebase for the key. The only problem with your current setup is that you would want to prevent duplicate names. The reason for this is that if you are not storing all the keys for each channel in app and have to query for the key, the only way to query the exact key is by the lone node "name". If a duplicate name exists then childAdded in the code I added to your did select row method will return two and there is no other data to help identify it.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == Section.currentChannelsSection.rawValue {
var channel = channels
if searchController.isActive && searchController.searchBar.text != "" {
channel = [filteredChannels[(indexPath as NSIndexPath).row]]
channelRef.queryOrdered(byChild: "name").queryEqual(toValue: channel.name).observe(.childAdded, with: {snapshot in
let currentID = snapshot.key
})
}
else
{
channel = [channels[(indexPath as NSIndexPath).row]]
channelRef.queryOrdered(byChild: "name").queryEqual(toValue: channel.name).observe(.childAdded, with: {snapshot in
let currentID = snapshot.key
})
}
self.performSegue(withIdentifier: "ShowChannel", sender: channel)
}
}

I would suggest you get the data for all of the channels on view did load:

override func viewDidLoad(){
channelRef.observe(.childAdded, with: {snapshot in
let data = snapshot.value as? [String:Any] ?? [:]
let key = snapshot.key
let name = data["name"]
let chnl = Channel.init(id:key, name:name)
self.channels.append(chnl)
self.tableView.reloadData()
})
}

When you use .childAdded a listener will be active for this VC so anytime you create a new channel this code will be called and reload your table.

Otherwise you can get they key directly when you create the channel:

@IBAction func createChannel(_ sender: AnyObject) {
if let name = newChannelTextField?.text {
let newChannelRef = channelRef.childByAutoId()
let channelItem = [
"name": name
]
newChannelRef.setValue(channelItem)
let channelKey = newChannelRef.key
let newChannel = Channel.init(id:channelKey, name:name)
self.channels.append(newChannel)
self.tableView.reloadData()
}

}

Just note if you go this route there are no active listeners for any new items added which means if another device is adding a channel then other devices will not get the update. Its better to pick up the newly created data from firebase via query and reload the table when you add your data to the array.

Here is a sample Channel class that should work for the above:

import Foundation
// import FirebaseDatabase // import this if you would like to use this class to handle data transactions

class Channel: NSObject {
// change either of these to var if they should be mutable
let id:String
let name:String
// initialize
init (_ id:String, name:String){
self.id = id
self.name = name
}
}

This way you have a model object that you can use. If you are unfamiliar with MVC coding style you should check it out. It makes applications much more efficient. You could take this Channel model and add the data retrieval coding so that this class handles the data for your controller. This is well beyond the scope of your post though. For now this class should work.

EDIT from last comment:
Add your prepareforsegue method in both of the query blocks during channel selection instead of after the if block as its possible the prepare for segue is executing before the query completes. One thing to note though, and I used to do the same thing as you before I realized this; is that you don't have to run a query to get the data for the selected cell at this point because its in your local arrays. Well, currently you are only listening for added children. You can listen for removed and changed children as well so that your local data is always updated and then when you select the cell you can simply access the filteredChannels/channels arrays directly and push the channel through the prepareforsegue method. I started doing this instead because querying during table selection always leaded to odd bugs which I had to find creative ways around.

The childRemoved and childChanged queries can be implemented the same as your current .childAdded method given you would want to keep handlers for the listeners to remove them on page deinit. However you can ignore this if you don't allow channel removal or updates.

Retrieve child by auto id value in firebase (TableView)

The "key" here is to ensure that when the data is initially loaded from Firebase you keep the node key intact. So for example. say you have a messaging app that has posts. Here's a class that would store the data from Firebase

struct PostStruct {
post_key = ""
post_text = ""
posted_by_uid = ""
}

and then those structs would be used to populate your dataSource array.

Given the above structure:

When your dataSource is initially populated from Firebase, as you read in each post node, create a post struct, populate it with data from Firebase and store it in a dataSource, typically an array.

When you swipe to delete there are about 100 options for handling the actual delete process but here are a couple:

1) Your tableView is backed by an array. If you swipe to delete row 2 (for example), inspect the object (struct) to be deleted, capture the post_key from the stuct, then delete the node from Firebase (since you know the node key) and then query the array for that object key, delete the row in the array and reload your tableView/update the UI.

2) When you swipe to delete a row, inspect the object and obtain the post_key. Then remove the object from Firebase. That would trigger a .childRemoved event (assuming you've attached the corresponding listener). When your app receives that event, determine which object it is (via key or other means) and remove it from the array and reload the tableView.

3) If you swipe to delete row 2, get the struct from row 2 in your dataSource array, read the key from that struct, remove row 2, remove the object from Firebase and reload the tableView.

There are many, many other way to tackle this; your dataSource array could store the actual snapshot data from firebase or it could store a series of key: value pairs with the key being the node key and the value being the data within that node (as a stuct, class, string etc).

Edit:

Some additional info to clarify the above.

Supposed we are using the structure above and firebase has matching nodes like this

root
posts
post_key_0 //created via childByAutoId
post_text: "some post text"
posted_by_uid: "uid_0"
post_key_1 //created via childByAutoId
post_text: "another post"
posted_by_uid: "uid_1"

then to read the posts and populate a dataSource array:

struct PostStruct {
post_key = ""
post_text = ""
posted_by_uid = ""
}

var dataSourceArray = [PostStruct]()

func button0() {
let itemsRef = self.ref.child("items")
itemsRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let postKey = snap.key
let postText = dict["post_text"] as! String
let postedByUid = dict["posted_by_uid"] as! String
let post = PostStruct(post_key: postKey, post_text: postText, posted_by_uid: ppostedByUid)
self.dataSourceArray.append(post)
}
self.someTableView.reloadData()
})
}

from there it's pretty straightforward.

Assuming we are using option 3), when the user swipes to delete row 2 for example you get that post from the array, row 2

let post = self.dataSourceArray[2]
let postKey = post.post_key

now you know the firebase key so it can then be removed

let thisPostRef = fbRef.child("posts").child(postKey)
thisPostRef.remove()

and finally remove it from the array and refresh the tableView

self.dataSourceArray.remove(at: 2)
self.someTableView.reloadData()

The code would be different if you went with one of the other options but the concepts are similar and can be applied to each.

Swift Firebase Get childByAutoId Key When Setting

Try with

var ref: DatabaseReference!

ref = Database.database().reference()

let keyValue = self.ref.child(name_of_child).childByAutoId().key

Updating child value to Firebase iOS and referencing auto ID in other nodes

If I understand it correctly you want to create new key for a new plan, and then store information in other nodes with the same key. If that is the case, it'd look like this:

let newPlanetRef = _REF_PLANITS.childByAutoId()
newPlanetRef.updateChildValues(["Planit Title" : withTitle, "uid": uid])

let key = newPlanetRef.key

let childUpdate = [allImages : withImage, allDates: withDate]
_REF_ALL_IMAGES.child(key).updateChildValues(childUpdate)

This assumes that _REF_PLANITS is a DatabaseReference to /PlanIt/plans and _REF_ALL_IMAGES is a reference to /PlanIt/all_images.

Get parent of child in Firebase

Since you're looping over snapshot.children, the key of the parent is always going to be snapshot.key.


What I think you're trying to do is traverse the two level of child nodes under friendlies. But for that you will need two loops:

var REF_FRIENDLIES = Database.database().reference().child("friendlies")
REF.FRIENDLIES.queryOrderedByKey().observeSingleEvent(of: .value, with: {
snapshot in
snapshot.children.forEach({ (snapChild) in
let child = snapChild as! DataSnapshot
child.children.forEach({ (snapGrandchild) in
let grandchild = snapGrandchild as! DataSnapshot
print("Grandchild Key: \(grandchild.key)")
print("Grandchild Parent Key: \(child.key)")
})
})
})

I might be missing some null handling in the code, but I hope the flow is clear.

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
}
}


Related Topics



Leave a reply



Submit