Retrieve Firebase value and set SKLabelNode text - swift

This is probably a very simple question.
This is the database:
I want to retrieve this "New" value which is 1 and put on a SKLabelNode.
The problem is that this code is printing 10 correctly but setting nil to SKLabelNode on the emulator.
dbRef.observeSingleEvent(of: .value) { (snap: FIRDataSnapshot) in
if !snap.exists() {
return
}else{
print(snap.childSnapshot(forPath: "New").value!)
self.label.text = snap.childSnapshot(forPath: "New").value as! String?
}
}

Related

Firebase Database observeSingleEvent not working

I have a simple function in my code which gets the users name. However, when it comes to the line saying observeSingleEvent, it skips the whole closure and exits the function. Any ideas why?
func getUsersName() {
let userId = Auth.auth().currentUser?.uid
// It comes to the line below
ref?.child("users").child(userId!).child("name").observeSingleEvent(of: .value, with: { snapshot in
// It skips all of that
guard let value = snapshot.value as? NSDictionary else {
return
}
let name = value["name"] as? String ?? ""
print("Users name is: \(name)")
})
} // And comes here
I have it just like in the docs from firebase. The idea is that I have a pair: name: "users_name" and I want to get the users name and display it in a table view.

TableView creates duplicates cells

when the like button is tapped it should increase the number of likes on the cell thats related to it but im having an issue which it creates a totally new cell with the updated number of likes I believe the problem is coming from how im loading my cells I believe I also need to add the function remove() so it clears the old data after the snapshot listener takes effect but im not too sure
func loaddailymotivation() {
FirebaseReferece(.MotivationDAILY).addSnapshotListener { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) { // this line means if the chage that happened in the document was equal to added something
let data = diff.document.data()
print("we have\(snapshot.documents.count) documents in this array")
let dailyMotivationID = data["objectID"] as! String
let dailymotivationTitle = data["Motivation title"] as! String //calls the data thats heald inside of motivation title in firebase
let dailyMotivationScripture = data["daily motivation scripture"] as! String //calls the data thats heald inside of Motivation script in firebase
let dailyMotivationNumberOfLikes = data["Number of likes in daily motivation post"]as! Int
let MdataModel = motivationDailyModel(RealMotivationID: dailyMotivationID, RealmotivationTitle: dailymotivationTitle, RealmotivationScrip: dailyMotivationScripture, RealmotivationNumberOfLikes: dailyMotivationNumberOfLikes)
self.motivationThoughts.append(MdataModel)
}
//===== //=====
if (diff.type == .modified) {
print("Modified data: \(diff.document.data())")
let newdata = diff.document.data()
let dailyMotivationID = newdata["objectID"] as! String
let dailymotivationTitle = newdata["Motivation title"] as! String //calls the data thats heald inside of motivation title in firebase
let dailyMotivationScripture = newdata["daily motivation scripture"] as! String //calls the data thats heald inside of Motivation script in firebase
let dailyMotivationNumberOfLikes = newdata["Number of likes in daily motivation post"]as! Int
let MdataModel = motivationDailyModel(RealMotivationID: dailyMotivationID, RealmotivationTitle: dailymotivationTitle, RealmotivationScrip: dailyMotivationScripture, RealmotivationNumberOfLikes: dailyMotivationNumberOfLikes)
self.motivationThoughts.append(MdataModel)
// here you will receive if any change happens in your data add it to your array as you want
}
DispatchQueue.main.async {
self.tableview.reloadData()
}
}
}
}
Both branches do exactly the same.
In the modified branch you have to get the corresponding object in motivationThoughts, update it and put it back, rather than creating a new object.
Something like
if diff.type == .modified {
print("Modified data: \(diff.document.data())")
let newdata = diff.document.data()
let objectID = newdata["objectID"] as! String
guard let dailymotivationIndex = motivationThoughts.firstIndex(where: {$0.dailyMotivationID == objectID}) else { return }
var dailymotivation = self.motivationThoughts[dailymotivationIndex]
let dailyMotivationNumberOfLikes = newdata["Number of likes in daily motivation post"] as! Int
dailymotivation.RealmotivationNumberOfLikes = dailyMotivationNumberOfLikes
self.motivationThoughts[dailymotivationIndex] = dailymotivation
}
And I recommend to reload only the row in the modified branch rather than the entire table view.

Item keeps getting added to Tableview even if I just have one in my DB

I have this code and I call it every time I click on a button and call another viewcontroller where I call fetchVinylData inside viewWillappear. The problem is everytime I click a button to go to this VC it adds one item to the tableview even if I only have one inside my database.I am guessing is because my array keeps getting fed even if there is only one record in my database.How do I delete from my array so I don't get many values inside my tableView only the ones that is saved on my firebase database?I tried to add myArray.removeAll() inside fetchrequest before I load the vinyl to the array but my app crashs eventually
func fetchVinylData() {
SVProgressHUD.show()
guard let currentUID = Auth.auth().currentUser?.uid else { return }
dbRef.child("vinylsOUT").child(currentUID).observe(.childAdded) { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String,AnyObject> else { return }
let vinyl = Vinyl(dictionary: dictionary)
self.vinyls.append(vinyl)
self.vinyls.sort(by: { (vinyl1, vinyl2) -> Bool in
return vinyl1.artist < vinyl2.artist
})
self.tableView.reloadData()
}
SVProgressHUD.dismiss()
}
thank yo very much
You are appending to your array every time you get back data from Firebase:
- self.vinyls.append(vinyl)
You can just override your current vinyls array by doing:
self.vinyls = [Vinyl]()
before you fetch the new data from Firebase.
That would look like this:
func fetchVinylData() {
SVProgressHUD.show()
guard let currentUID = Auth.auth().currentUser?.uid else { return }
self.vinyls = [Vinyl]() // <- here you reset the array
dbRef.child("vinylsOUT").child(currentUID).observe(.childAdded) { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String,AnyObject> else { return }
let vinyl = Vinyl(dictionary: dictionary)
self.vinyls.append(vinyl)
self.vinyls.sort(by: { (vinyl1, vinyl2) -> Bool in
return vinyl1.artist < vinyl2.artist
})
self.tableView.reloadData()
}
SVProgressHUD.dismiss()
}

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

Showing just one image at the time from database (Swift and Firebase)

First of all, I am new in this, so please do not make fun of me :)
Basically, I am trying to show and Image of a product but if the client refuses the product this item will not appear on his account. That is why I am creating another table Rejected (setAcceptedOrRejected) where I put the ID of the product and the Id of the client so I wont see the item he rejected before.
What I tried here it was to get the List (Good) with all the items and the (Bad) with the rejected items. Then compare it to display the picture of the item again.
My problem is that I want to show only 1 picture at the time, if the client refuses then it will show the next one and so on but it wont show that picture again.
I hope you can really help me with this one.
Thank you
func updateImage() {
createListProductsBad ()
var badnot = ""
for bad2 in listProductsBad{
badnot = bad2
}
Database.database().reference().child("Products").child(bad2)queryOrderedByKey().observe(.childAdded, with: { snapshot in
let userInfo = snapshot.value as! NSDictionary
let storageRef = Storage.storage().reference(forURL: profileUrl)
storageRef.downloadURL(completion: { (url, error) in
do {
let data = try Data(contentsOf: url!)
let image = UIImage(data: data as Data)
self.productPhoto.image = image
}
catch _ {
print("error")
}
})
})
}
func setAcceptedOrRejected() {
let notThankyou = [ "ProductID": ProductId,
"UserID": userUID
] as [String : Any]
self.storyboard?.instantiateViewController(withIdentifier: "Home")
self.refProducts.child("Rejected").childByAutoId().setValue(notThankyou)
}
func createListProductsGood () {
Database.database().reference().child("Products").queryOrderedByKey().observe(.childAdded, with: { snapshot in
if !snapshot.exists() { return }
let userInfo = snapshot.value as! NSDictionary
let goodID = String(snapshot.key)
for prod in self.listProductsBad{
if (prod == goodID){
print("Not good **********************")
}else{
if (goodID != "" ){
self.listProductsGood.append(prod)
}
}
}
})
}
func createListProductsBad () {
Database.database().reference().child("Rejected").queryOrderedByKey().observe(.childAdded, with: { snapshot in
let userInfo = snapshot.value as! NSDictionary
let currentID = userInfo["UserID"] as! String
let badProduct = userInfo["ProductID"] as! String
if (self.userUID == currentID ){
self.listProductsBad.append(badProduct)
}
})
}
}
//These can also be swift's dictionaries, [String: AnyObject] or possibility arrays if done correctly. All depends on your style of programming - I prefer NSDictionaries just because.
let availableKeys: NSMutableDictionary = [:]
let rejectedKeys: NSMutableDictionary = [:]
//Might be a better way for you. Depends on what you are looking for.
func sortItems2() -> NSMutableDictionary{
for rejKey in rejectedKeys.allKeys{
//Removes if the rejected key is found in the available ones
availableKeys.remove(rejKey)
}
return availableKeys
}