I have a MapView where you can add or delete MKAnnotation via Firebase .
When you add a new alert it get posted to Firebase on which I have observers both for added and removed snapshots.
Firebase gets updated correctly, map gets updated correctly for added snapshots, but doesn't get updated for deleted ones. I check in both functions that the arrays where I save the alerts are correctly updated before and after receiving the snapshots and they indeed are correct.
So the only thing not happening is the icon removed from the map.. when I use self.mapView.removeAnnotation(annotationToRemove)which I define based on the incoming snapshot.
If I instead remove all the annotations and re add them from the array it works correctly.It's just horrible to see this continuously updating map.. seems more like a glitching error then an updating map.
Can you see why removing the specific one doesn't work??
As always thank you very much.
This is the code:
func getAlerts(setCompletion: #escaping (Bool) -> ()) {
// self.mapView.removeAnnotations(mapView.annotations)
// MapArray.alertNotificationCoordinatesArray.removeAll()
// MapArray.userAlertNotificationArray.removeAll()
print(" MapArray.alertNotificationCoordinatesArray before getAlerts is: \(MapArray.alertNotificationCoordinatesArray)")
print(" MapArray.userAlertNotificationArray before getAlerts is: \(MapArray.userAlertNotificationArray)")
ref = Database.database().reference()
// ref?.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Community").child("Alert Notifications").observe(.childAdded, with: { (snapshot) in
ref?.child("Continent").child("Europe").child("Country").child("\(String(describing: userDetails.country!))").child("Region").child("\(String(describing: userDetails.region!))").child("City").child("\(String(describing: userDetails.city!))").child("Community").child("Alert Notifications").observe(DataEventType.childAdded, with: { (snapshot) in
// self.mapView.removeAnnotations(self.mapView.annotations) // wrong!! causes all annotations to be deleted when any new one is notified by anyone
// print(" added snapshot is: \(snapshot)")
guard let data = snapshot.value as? [String:String] else { return }
// guard let firebaseKey = snapshot.key as? String else { return }
let firebaseKey = snapshot.key
let dataLatitude = data["Latitude"]!
let dataLongitude = data["Longitude"]!
let type = data["Description"]!
// let id = Int(data["Id"]!)
let id = data["Id"]!
let userName = data["user"]!
let alertImageUrl = data["alertImageUrl"] ?? ""
let alertImageName = data["alertImageName"] ?? ""
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
let recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
let userAlertAnnotation = UserAlert(type: type, coordinate: recombinedCoordinate, firebaseKey: firebaseKey, title: type, id: id, userName: userName, alertImageUrl: alertImageUrl, alertImageName: alertImageName)
MapArray.userAlertNotificationArray.append(userAlertAnnotation) // array of notifications coming from Firebase
MapArray.alertNotificationCoordinatesArray.append(recombinedCoordinate) // array for checkig alerts on route
print(" MapArray.alertNotificationCoordinatesArray after getNewerAlerts is: \(MapArray.alertNotificationCoordinatesArray)")
print(" MapArray.userAlertNotificationArray after getNewerAlerts is: \(MapArray.userAlertNotificationArray)")
self.mapView.addAnnotation(userAlertAnnotation)
setCompletion(true)
// self.mapView.addAnnotations(MapArray.userAlertNotificationArray)
})
}
func getDeletedAlerts(setCompletion: #escaping (Bool) -> ()) {
ref?.child("Continent").child("Europe").child("Country").child("\(String(describing: userDetails.country!))").child("Region").child("\(String(describing: userDetails.region!))").child("City").child("\(String(describing: userDetails.city!))").child("Community").child("Alert Notifications").observe(DataEventType.childRemoved, with: { (snapshot) in
print(" MapArray.userAlertNotificationArray before getDeletedAlerts snapshot is: \(MapArray.userAlertNotificationArray)")
print(" MapArray.alertNotificationCoordinatesArray before getDeletedAlerts snapshot is: \(MapArray.alertNotificationCoordinatesArray)")
print(" removed snapshot is: \(snapshot)")
guard let data = snapshot.value as? [String:String] else { return }
let firebaseKey = snapshot.key
let dataLatitude = data["Latitude"]!
let dataLongitude = data["Longitude"]!
let type = data["Description"]!
// let id = Int(data["Id"]!)
let id = data["Id"]!
let userName = data["user"]!
let alertImageUrl = data["alertImageUrl"] ?? ""
let alertImageName = data["alertImageName"] ?? ""
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
let recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
let annotationToRemove = UserAlert(type: type, coordinate: recombinedCoordinate, firebaseKey: firebaseKey, title: type, id: id, userName: userName, alertImageUrl: alertImageUrl, alertImageName: alertImageName)
MapArray.userAlertNotificationArray.removeAll(where: { ($0.firebaseKey == firebaseKey) }) //remove the alert
MapArray.alertNotificationCoordinatesArray.removeAll(where: { ($0.latitude == recombinedCoordinate.latitude && $0.longitude == recombinedCoordinate.longitude) })
self.mapView.removeAnnotation(annotationToRemove)
// self.mapView.removeAnnotations(self.mapView.annotations)
// self.mapView.addAnnotations(MapArray.userAlertNotificationArray)
print(" MapArray.userAlertNotificationArray after getDeletedAlerts snapshot is: \(MapArray.userAlertNotificationArray)")
print(" MapArray.alertNotificationCoordinatesArray after getDeletedAlerts snapshot is: \(MapArray.alertNotificationCoordinatesArray)")
setCompletion(true)
})
}
You create the annotation and try to remove it which for sure not added to the mapView
let annotationToRemove = UserAlert(
self.mapView.removeAnnotation(annotationToRemove)
While you should do
for item in self.mapView.annoations {
if let ann = item as? UserAlert , ann.id == annotationToRemove.id {
self.mapView.removeAnnotation(ann)
}
}
Related
I am using firebase for chat app.when I try to send a message. than message, table got value but not update chat-message table. I refer to this link Here [https://github.com/DevSurya/ChatApp-Swift-And-Firebase].
when I run demo its working fine. Observe method is not calling in my case and collectionview is not refreshing
This is how I write data :
private func sendMessageWithProperty(_ property: [String: AnyObject]){
let ref = Database.database().reference().child("messages")
let childRef = ref.childByAutoId()
let toId = user!.id!
let fromId = Auth.auth().currentUser!.uid
let timeStamp = NSNumber.init(value: Date().timeIntervalSince1970)
var values: [String : AnyObject] = ["toId":toId as AnyObject, "fromId":fromId as AnyObject, "timeStamp":timeStamp]
values = values.merged(with: property)
childRef.updateChildValues(values)
childRef.updateChildValues(values) { (error, ref) in
if error != nil {
print(error!)
return
}
self.inputTextField.text = nil
let userMessageRef = Database.database().reference().child("user-messages").child(fromId).child(toId)
let messageId = childRef.key
userMessageRef.updateChildValues([messageId: 1])
let recipentUserMessageRef = Database.database().reference().child("user-messages").child(toId).child(fromId)
recipentUserMessageRef.updateChildValues([messageId: 1])
}
}
This is how I read data
func observeMessage() {
guard let uid = Auth.auth().currentUser?.uid, let toId = user?.id else {
return
}
let userMessageRef = Database.database().reference().child("user-messages").child(uid).child(toId)
userMessageRef.observe(.childAdded, with: { (snapshot) in
let messageId = snapshot.key
let messagesRef = Database.database().reference().child("messages").child(messageId)
messagesRef.observeSingleEvent(of: .value, with: { (snapshot) in
guard let dict = snapshot.value as? [String: AnyObject] else {
return
}
let message = Message()
message.setValuesForKeys(dict)
self.messages.append(message)
DispatchQueue.main.async {
self.collectionView?.reloadData()
let indexpath = NSIndexPath.init(item: self.messages.count-1, section: 0)
self.collectionView?.scrollToItem(at: indexpath as IndexPath, at: .bottom, animated: true)
}
}, withCancel: nil)
}, withCancel: nil)
}
The ObserveMessage() function get automatically called when there is an update in database.but in my case its not get called. I think the problem is with user-messages table: it is not created when I send message.
I have a function that listen to Firebase for added and removed childs in my database.
I do a print for the array where I store incoming data from database before observers and one after the observers so to check if the logic is working, and it does. Snapshots append and remove the right object to/from the array.
Now I have the problem that on console I get more than one print per call, in both .childAdded and .childRemoved. It's not random, from fresh start the pattern goes like, 1st add to Firebase gives me 2 prints. And from than it's incremental. 2nd add or 1st remove will give me 3 prints. etc etc..
It's almost like it has a counter..
Removing the observers in viewWillDisappeardoesn't change anything..
In Firebase I store MKAnnotation's coordinates. When I add one annotation I post it, I get it back through the observer's snapshotand I add it to the map. When I remove it I remove it from Firebase and I get a snapshot from .childRemovedobserver and I update the map. What I noticed by putting a breakpoint for each observer is that on the.childRemovedit loops incrementally as the prints. That should mean that the annotation gets added that number of times to the map by the .chilAddedobserver right? I thought I solved this but it's so clear that I haven't. Can you spot the problem here?
Many thanks as usual
Here's the function:
func getAlerts(setCompletion: #escaping (Bool) -> ()) {
self.mapView.removeAnnotations(mapView.annotations)
MapArray.alertNotificationCoordinatesArray.removeAll()
MapArray.userAlertNotificationArray.removeAll()
print(" MapArray.alertNotificationCoordinatesArray before getNewerAlerts is: \(MapArray.alertNotificationCoordinatesArray)")
print(" self.userAlertNotificationArray before getNewerAlerts is: \(MapArray.userAlertNotificationArray)")
ref = Database.database().reference()
ref?.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Community").child("Alert Notifications").observe(.childAdded, with: { (snapshot) in
// self.mapView.removeAnnotations(self.mapView.annotations) //
print(" added snapshot is: \(snapshot)")
guard let data = snapshot.value as? [String:String] else { return }
// guard let firebaseKey = snapshot.key as? String else { return }
let firebaseKey = snapshot.key
// let date = data!["Date"]
// let time = data!["Time"]
let dataLatitude = data["Latitude"]!
let dataLongitude = data["Longitude"]!
let type = data["Description"]!
let id = Int(data["Id"]!)
let userName = data["user"]!
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
let recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
let userAlertAnnotation = UserAlert(type: type, coordinate: recombinedCoordinate, firebaseKey: firebaseKey, title: type,id: id!, userName: userName)
MapArray.userAlertNotificationArray.append(userAlertAnnotation) // array of notifications coming from Firebase
MapArray.alertNotificationCoordinatesArray.append(recombinedCoordinate) // array for checkig alerts on route
print(" MapArray.alertNotificationCoordinatesArray after getNewerAlerts is: \(MapArray.alertNotificationCoordinatesArray)")
print(" self.userAlertNotificationArray after getNewerAlerts is: \(MapArray.userAlertNotificationArray)")
setCompletion(true)
self.mapView.addAnnotations(MapArray.userAlertNotificationArray)
})
ref?.child("Continent").child("Europe").child("Country").child("Italy").child("Region").child("Emilia-Romagna").child("City").child("Bologna").child("Community").child("Alert Notifications").observe(.childRemoved, with: { (snapshot) in
print(" self.userAlertNotificationArray before getDeletedAlerts snapshot is: \(MapArray.userAlertNotificationArray)")
print(" MapArray.alertNotificationCoordinatesArray before getDeletedAlerts snapshot is: \(MapArray.alertNotificationCoordinatesArray)")
print(" removed snapshot is: \(snapshot)")
guard let data = snapshot.value as? [String:String] else { return }
let firebaseKey = snapshot.key
// let date = data!["Date"]
// let time = data!["Time"]
let dataLatitude = data["Latitude"]!
let dataLongitude = data["Longitude"]!
let type = data["Description"]!
let id = Int(data["Id"]!)
let userName = data["user"]!
let doubledLatitude = Double(dataLatitude)
let doubledLongitude = Double(dataLongitude)
let recombinedCoordinate = CLLocationCoordinate2D(latitude: doubledLatitude!, longitude: doubledLongitude!)
_ = UserAlert(type: type, coordinate: recombinedCoordinate, firebaseKey: firebaseKey, title: type,id: id!, userName: userName)
MapArray.userAlertNotificationArray.removeAll(where: { ($0.firebaseKey == firebaseKey) }) //remove the alert
MapArray.alertNotificationCoordinatesArray.removeAll(where: { ($0.latitude == recombinedCoordinate.latitude && $0.longitude == recombinedCoordinate.longitude) })
self.mapView.removeAnnotations(self.mapView.annotations)
self.mapView.addAnnotations(MapArray.userAlertNotificationArray)
print(" self.userAlertNotificationArray after getDeletedAlerts snapshot is: \(MapArray.userAlertNotificationArray)")
print(" MapArray.alertNotificationCoordinatesArray after getDeletedAlerts snapshot is: \(MapArray.alertNotificationCoordinatesArray)")
setCompletion(true)
})
}
I'm Trying to check if the rooms's value 'Owner' equals to the current user id if so then fetch all data including the key value and continue checking other children of 'rooms'
I was trying, but I fail finding the solution though it might seem easy so please help me with your suggestions or ideas. My code so far :
Database.database().reference().child("rooms").queryOrdered(byChild: "Owner").observeSingleEvent(of: .value, with: { (snapshot) in
let currentUser = Auth.auth().currentUser?.uid
if !snapshot.exists() {
print("No data found")
return
}
var rooms = snapshot.value as! [String:AnyObject]
let roomKeys = Array(rooms.keys)
for roomKey in roomKeys {
guard
let value = rooms[roomKey] as? [String:AnyObject]
else
{
continue
}
let title = value["title"] as? String
let description = value["description"] as? String
let roomPictureUrl = value["Room Picture"] as? String
let longitude = value["Longtitude"] as? String
let latitude = value["Latitude"] as? String
let dateFrom = value["Date From"] as? String
let dateTo = value["Date To"] as? String
let owner = value["Owner"] as? String
let myRooms = Room(roomID: roomKey,title: title!, description: description!, roomPicutreURL: roomPictureUrl!, longitude: longitude!, latitude: latitude!, dateFrom: dateFrom!, dateTo: dateTo!, owner: owner!)
self.rooms.append(myRooms)
self.tableView.reloadData()
print(snapshot.value)
}
})
You're missing the value in your query:
Database.database().reference()
.child("rooms")
.queryOrdered(byChild: "Owner")
.queryEqual(toValue: "STbz...")
.observeSingleEvent(of: .value, with: { (snapshot) in
See for this and more query operators, the documentation on filtering data.
Mark:- Swift 5
Database.database().reference().child("user")
.queryOrdered(byChild: "UserPhoneNumber") //in which column you want to find
.queryEqual(toValue: "Your phone number or any column value")
.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.childrenCount > 0
{
if let snapShot = snapshot.children.allObjects as? [DataSnapshot] {
//MARK:- User Exist in database
for snap in snapShot{
//MARK:- User auto id for exist user
print(snap.key)
break
}
}
}
else if snapshot.childrenCount == 0
{
//MARK:- User not exist no data found
}
})
I have this function that it will be triggered every time a user changes his picture, and will get the profilePictureUrl of the current user and update all posts matching the currentUser in the database. Works fine! Is doing the job. How do I update the indexPath of those particular cells? Right now my cells images are empty after the update.
var pathToPictures = [Pictures]()
func updateAllImagesOfCurrentUserInDatabase() {
//refrences
let ref = FIRDatabase.database().reference()
let uid = FIRAuth.auth()?.currentUser?.uid
//match the user ID value stored into posts with current userID and get all the posts of the user
let update = ref.child("posts").queryOrdered(byChild: "userID").queryEqual(toValue: uid)
update.observe(FIRDataEventType.value, with: { (snapshot) in
self.pathToPictures.removeAll()
if snapshot.value as? [String : AnyObject] != nil {
let results = snapshot.value as! [String : AnyObject]
for (_, value) in results {
let pathToPostPicture = Pictures()
if let pathToImage = value["pathToImage"] as? String , let postID = value["postID"] as? String {
pathToPostPicture.postImageUrl = pathToImage
pathToPostPicture.postID = postID
self.pathToPictures.append(pathToPostPicture)
print("Image and POST ID: \(pathToPostPicture.postImageUrl!)")
print("Post ID is : \(postID)")
if FIRAuth.auth()?.currentUser?.uid == uid {
ref.child("Users_Details").child(uid!).child("profileImageUrl").observeSingleEvent(of: .value, with: { (userSnapshot) in
print(userSnapshot)
let userIMageUrl = userSnapshot.value as! String
pathToPostPicture.postImageUrl = userIMageUrl
self.pathToPictures.append(pathToPostPicture)
print("This is the image path:" + userIMageUrl + String(self.pathToPictures.count))
// Update the Database
let postIDCount = pathToPostPicture.postID!
let updatedUserData = ["posts/\(postIDCount)/pathToImage": pathToPostPicture.postImageUrl!]
print("This is THE DATA:" , updatedUserData)
ref.updateChildValues(updatedUserData as Any as! [AnyHashable : Any])
})
}
print(self.pathToPictures.count)
}
}
} else {
print("snapshot is nill - add some data")
}
self.collectionView?.reloadData()
})
}
I am currently building an app in Firebase and I want to get all the users pineapple rate.
This is the tree:
user1: uid1 {
fruits: {
apple: 3
pineapple: 5
}
}
user2: uid2 {
fruits: {
apple: 4
pineapple: 2
}
}
I tried this code:
var ref = FIRDatabase.database().reference()
ref.queryOrderedByChild("fruits")
.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if ( snapshot.value is NSNull ) {
print("not found")
} else {
for child in snapshot.children {
let rate = child.value["pineapple"] as! String
print(rate)
}
}
})
But it gives me an error of unwrapping Nil.
Picture of the structre:
This is supposed to be like this
var ref = FIRDatabase.database().reference()
ref.queryOrderedByChild("user2")
.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if snapshot.exists() {
for child in (snapshot.value?.allValues)! {
if let fruits = child["Fruits"] as? [String:String]{
let rate = fruits["pineapple"]
print(rate)
}
}
}
})
It seems this just needs a deep query?
let ref = self.myRootRef.child("parent_node")
ref.queryOrderedByChild("Fruits/pineapple").observeSingleEventOfType(.Value, withBlock: {
snapshot in
if ( snapshot.value is NSNull ) {
print("not found")
} else {
for child in snapshot.children {
let key = child.key as String
let dict = child.value["Fruits"] as! NSDictionary
let pineapple_count = dict["pineapple"] as! Int
print("key = \(key) count = \(pineapple_count)")
}
}
})
and the output is
key = uid_1 count = 1
key = uid_0 count = 3
key = uid_2 count = 21
Try out this code below (Xcode 8.3.3, Swift 3 and Firebase 3 )
var ref = Database.database().reference().child("fruits")
ref.observeSingleEvent(of: .value, with: {
(snapshot) in
if let fruitPost = snapshot.value as? Dictionary<String,AnyObject> {
for(key, value) in fruitPost {
if let fruitData = value as? Dictionary<String,AnyObject> {
if let fruits = fruitData["pineapple"] as? String{
let rate = fruits
print(rate)
}
}
}
}
Goodluck mate!