Problem statement:
I am currently working on an app that will track all the buses in my college. Each bus is equipped with a GPS module that sends updated coordinate along with heading to the cloud fireStore every 5 seconds. On the application side I want to read that updated coordinate whenever it changes.
Cloud firestore:
busCurrentLoc (shown in the image) has different bus numbers in it and each bus number has their respective longitude and latitude along with heading.
Application side:
The user is provided a screen where he can select which bus he wants to track. When he selects the bus number he is shown the Map screen where the bus's real time location is updated every 5 seconds. I have already done the selection process. The Real-Time tracking is the issue.
I have included necessary comments about each and every variable in the code below. The problem i am facing is updating the currentLocation variable whenever there is a change in the cloud firestore.
Code:
//The mapview outlet
@IBOutlet var mapView: MKMapView!
//The variable which stores the current coordinates of the bus from cloud firebase
var currentLocation = [String: CLLocationCoordinate2D]()
//This variable is assigned from the previous ViewController during segue.
var selectedNum: String
let db = Firestore.firestore()
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
//Function to get the coordinate from cloud firestore
getCoordinates()
}
//MARK: - Get coordinates
/**
Function to get coordinates from the Cloud firestore and store it in the global "currentLocation" variable.
*/
func getCoordinates() {
db.collection("busCurrentLoc").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
if document.documentID == self.selectedNumber {
let latitude = document.data()["latitude"]
let longitude = document.data()["longitude"]
let coord: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude as! CLLocationDegrees, longitude: longitude as! CLLocationDegrees)
self.currentLocation = ["Location": coord]
// prints : ["Location": __C.CLLocationCoordinate2D(latitude: 12.89307834, longitude: 80.1411217)]
print(self.currentLocation)
self.DrawBus()
}
}
}
}
//This function should draw a bus/annotation on the currentLocation.
DrawBus(at: currentLocation)
}
//MARK: - Draw bus at currentLocation
/**
Function to Draw a bus at currentLocation.
- Parameters:
currentLocation
*/
func drawBus(coordinate at: [String: CLLocationCoordinate2D]()) {
let annotations = MKPointAnnotation()
annotations.title = "Bus Location"
annotations.coordinate = coordinate["Location"] ?? CLLocationCoordinate2D(latitude: 0, longitude: 0)
mapView.addAnnotation(annotations)
}
The annotation is added to the screen and it is displayed. But when i try changing the coordinate in the Cloud firestore the coordinate doesn't change or the annotation is not getting updated. Kindly help me solve this issue.
I managed to solve this issue by using addSnapshotListener instead of getDocument
db.collection("busCurrentLoc").addSnapshotListener{ (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
if document.documentID == self.selectedNumber {
let latitude = document.data()["latitude"]
let longitude = document.data()["longitude"]
self.currentHeading = document.data()["heading"] as! CGFloat
let coord: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude as! CLLocationDegrees, longitude: longitude as! CLLocationDegrees)
self.currentLocation = ["Location": coord]
print(self.currentLocation)
self.DrawBus()
}
}
}
}