Retrieve only the Value without the Key in Firebase - swift

So I'm trying to retrieve only the "second" value of a child from my firebase database.
The structure looks like this:
And what I'm getting as an output is this:
However what I actually want is just:
someURL.com
Ideally even without the https or http (where I probably need an if to check, since it is not known for all of them in advance). I guess there are 2 options, either unwrapping the string in Swift, or (what I was hoping for) just retrieving the actual value without the brackets and "url" in the beginning. I couldn't find a similar problem on here yet.
My code for retrieving:
dataSource?.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
let snap = obj as! FIRDataSnapshot
let childString = snap.value as! [String : AnyObject]
cell.textLabel?.text = String(childString)
}

Try this
dataSource?.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
let snap = obj as! FIRDataSnapshot
let childString = snap.value as! [String : AnyObject]
if let url = childString["url"] as? String {
cell.textLabel?.text = url
} else {
print("No value for url")
}
}
childString variable you are using is a dictionary which has values for keys. You need to fetch the value for the key "url".

Related

Issues when trying to remove the firebase reference

I am having some issues while trying to delete one of the tableView row - in my case I was trying to delete the data from Firebase and then reload the table view.
See the function below:
func deleteMeds() {
Database.database().reference().child("Meds_Database").child("UsersID").child((Auth.auth().currentUser?.uid)!).child("User_Medications").observe(DataEventType.childRemoved, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
let medication = Meds()
medication.medName = (dictionary["Medication_Name"]) as! String
medication.medDosage = (dictionary["Medication_Dosage"]) as! String
medication.medEdit = (dictionary["Medication_Frequency"]) as! String
medication.medAlarm = (dictionary["Medication_Reminder"]) as! String
self.meds.remove(at: 0)
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
print(snapshot)
}, withCancel: nil)
}
I think I am getting confused with the Firebase Syntax... Can somebody help me? The database is like this:
I am sure someone can help
You only need to delete the relavant object not always index 0 here
self.meds.remove(at: 0)
So replace it with
self.meds = self.meds.filter{ $0 != medication }
and adopt the Equatable protocol

Firebase Add New Key/Value to Pre-existing database without crashing xcode

` let query = ref?.child("Reviews").queryOrdered(byChild: "UserID").queryEqual(toValue: myUser.userId)
query?.observeSingleEvent(of: .value) { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let uid = dict["UserID"] as! String
let review = dict["Body"] as! String
let rating = dict["Rating"] as! String
let titleID = dict["TitleID"] as! String
let reviewID = dict["ReviewID"] as! String
let ratingID = dict["RatingID"] as! String
`
THE ERROR OCCURS AT THE ratingID call to the database. It unwraps nil.
I am trying to adapt a pre existing Firebase database with a new key/value.
I then try to display entries in my tableview and I get a crash with unwrap returning nil. I know why this is happening and it's because the previous data does not have the new key/value I want to include in the node going forward. I have tried many different things such as if let and guard let without much fortune. How do I add new key/Values and still have the tableview read entries that don't have the new value?
I include an image of the current node and I want to add a 'RatingsID' to the node. When I do, I get the unwrap nil error.
Database node prior to new key/value
Your code is super close, just need to protect the code in case the ratingID key doesn't exist.
So change
let ratingID = dict["RatingID"] as! String
to
let ratingID = dict["RatingID"] as! String ?? ""
So if the RatingID node does not exist, you'll set ratingID to an empty string (or whatever string you want)
You could also code it to only operate on the value of that key if the node exists (not nil)
if let someVal = dict["xxx"] {
//do something with someVal
} else {
print("xxx node wasn't found")
}
Here's a complete example: We are reading some messages from the messages node and some of them have a test_key node and some dont. For those that don't, default string is assigned to test
let postsRef = self.ref.child("messages")
postsRef.observe(.childAdded) { snapshot in
let dict = snapshot.value as! [String: Any]
let msg = dict["msg"] as! String
let test = dict["test_key"] ?? "default string"
print(msg, test)
}

Using Guard in an Init?

Everything works swimmingly except for when I do a random string like "fds", how would I correctly and efficiently use a guard to protect from this sort of error?
init(weatherData: [String: AnyObject]) {
city = weatherData["name"] as! String
let weatherDict = weatherData["weather"]![0] as! [String: AnyObject]
description = weatherDict["description"] as! String
icon = weatherDict["icon"] as! String
let mainDict = weatherData["main"] as! [String: AnyObject]
currentTemp = mainDict["temp"] as! Double
humidity = mainDict["humidity"] as! Int
let windDict = weatherData["wind"] as! [String: AnyObject]
windSpeed = windDict["speed"] as! Double
}
how would I correctly and efficiently use a guard to protect from this sort of error?
Why would you want to? If the caller does not hand you a dictionary whose "name" key is present and is a string, you are dead in the water because you cannot initialize city. You want to crash.
If you would like to escape from this situation without actually crashing, then make this a failable initializer and fail (return nil) if the dictionary doesn't contain the needed data. This effectively pushes the danger of crashing onto the caller, because the result will be an Optional that might be nil, and the caller must check for that.
init?(weatherData: [String: AnyObject]) {
guard let city = weatherData["name"] as? String else {return nil}
self.city = city
// ... and so on ...
}
But what I would do is none of those things. I would rewrite the initializer as init(city:description:icon:currentTemp:humidity:windSpeed:) and force the caller to parse the dictionary into the needed data. That way, if the data is not there, we don't even try to initialize this class in the first place. My argument would be that it is the caller's job to parse the dictionary; this class should have no knowledge of the structure of some complex dictionary pulled off the Internet (or whatever the source is).

Retrieve a Childs Child in Firebase - Unwrap unique-post-ids

I am trying to unwrap data in childs from childs basically. My current database structure looks like this:
- user-posts
- <user-id>
- user-data
- <unique-post-id> (As a result from childByAutoId)
- the data I want to display
- <unique-post-id> (As a result from childByAutoId)
- the data I want to display
...
-<user-id>
-...
-<user-id>
...
So as it can be seen, the actual data I want to retrieve is always a child of <unique-post-id>, which is automatically generated when the data is written to the database. Retrieving from the database I so far only get:
- <unique-post-id>
- <unique-post-id>
- ...
Is there a way of unwrapping those and display their childs? What is working for me now is displaying all the unique post id's, but I can't figure out how to get then the child below them, and that for all of them.
The code I'm using to retrieve the data:
func getQuery() -> FIRDatabaseQuery {
let myTopPostsQuery = (ref.child("user-posts")).child(getUid()).child("user-data")
return myTopPostsQuery
}
dataSource = FirebaseTableViewDataSource.init(query: getQuery(),cellReuseIdentifier: "Cellident", view: self.tableView)
dataSource?.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
let snap = obj as! FIRDataSnapshot
cell.textLabel?.text = snap.key as String
}
dataSource?.populateCellWithBlock { (cell: UITableViewCell, obj: NSObject) -> Void in
let snap = obj as! FIRDataSnapshot
cell.textLabel?.text = snap.key as! String
let childString = snap.value as! String
// If the child is another dictionary use `as! [String : AnyObject]`
}
But a different approach might go like this : -
ref.child("user-posts")).child(getUid()).child("user-data").observeEventType(.Value, withBlock: { (snap) in
if snap.exists(){
for each in snap as! [String : AnyObject] {
let childString = snap.Value as! String
}
}
})

ambiguous use of subscript swift 2.2

I have a lot of issues in my code with this error. Hopefully if someone can help me here than I can figure out the rest of the problems. I have updated to xcode 7.3 and running swift 2.2.
I have read that the compiler has been "more restrictive", and I have to tell it what the "intermediary" objects are. This is causing me some confusion and would love further explanation.
func getMessage(dictionary:NSDictionary)->String{
var message = String()
if let dict = dictionary["aps"] {
if let message:String = dict["alert"] as? String {
return message
}
else{
message = ""
}
}
return message
}
Another example:
for object in objects {
let getDriver = object.objectForKey("driver")
if let picture = getDriver!["thumbnailImage"] as? PFFile {
self.profilePictures.append(picture)
}
self.requestsArray.append(object.objectId as String!)
}
The type of a dictionary value is always AnyObject. Cast the type to something more specific for example
if let dict = dictionary["aps"] as? [String:AnyObject] {
then the compiler knows that key subscripting is valid and possible
The second example is similar: object is a dictionary and the compiler needs to know that the value for key driver is also a dictionary
if let getDriver = object.objectForKey("driver") as? [String:AnyObject] {
if let picture = getDriver["thumbnailImage"] as? PFFile {
...