Search code examples
swiftmapkitmapkitannotation

Reading a coordinate from the cloud firestore continously and updating the point on the map as the coordinate changes - Swift, apple mapkit


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.

This image shows the Cloud FireStore

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.

This image represents annotation that is displayed on the mapview

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.


Solution

  • 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()
                        }
                    }
                }
            }