Amrit Sidhu
Amrit Sidhu

Reputation: 1950

Add and remove observer for KVO "myLocation" in GMSMapView

I have searched through all the possible solutions but couldn't find the exact one. My problem is : I am using a navigation controller and a viewcontroller with GMSMapView. When I navigate to some other view from the GMSMapView, the app crashes with an exeption that "An instance 0x7f9b79c53c20 of class GMSMapView was deallocated while key value observers were still registered with it."

But if I try to remove the observer in viewwilldisappear or deinit, the app again crashes with an exception 'Cannot remove an observer for the key path "myLocation" from because it is not registered as an observer.

Can anyone help with the best solution. Here is my code:

override func viewDidLoad() {

open.target = self.revealViewController()
open.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())

locationManager.delegate = self
mapView.delegate = self

if (locationManager.respondsToSelector(Selector("requestWhenInUseAuthorization"))) {
locationManager.requestWhenInUseAuthorization()
}
 mapView.myLocationEnabled = true

placesClient = GMSPlacesClient()  
}

override func viewWillAppear(animated: Bool) {

    mapView.addObserver(self, forKeyPath: "myLocation", options: NSKeyValueObservingOptions.New, context: nil)

}

deinit{
removeObserver(self, forKeyPath: "myLocation", context: nil)

}
 override func viewWillDisappear(animated: Bool) {


   // removeObserver(self, forKeyPath: "myLocation")
}

 override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
    if !didFindMyLocation {
        let myLocation: CLLocation = change[NSKeyValueChangeNewKey] as CLLocation
        mapView.camera = GMSCameraPosition.cameraWithTarget(myLocation.coordinate, zoom: 15.0)
        mapView.settings.myLocationButton = true
        didFindMyLocation = true
    }
}

Upvotes: 4

Views: 1917

Answers (2)

Foti Dim
Foti Dim

Reputation: 1371

The new closure based KVO for Swift 3.2+ goes like that:

class myCustomView: UIView {
    let camera = GMSCameraPosition(target: CLLocationCoordinate2D(latitude: 52.5067614, longitude: 13.2846524), zoom: 10, bearing: 0, viewingAngle: 0)
    lazy var mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
    private var observation: NSKeyValueObservation?

    func startObserving() {
       self.observation = self.mapView.observe(\.myLocation, options: [.new, .old], changeHandler: { _, change in
                guard let newLocation = change.newValue else { return }
                //Do something with newlocation
            })
    }
}

Call the startObserving() function wherever you want.

Invalidating the observer is not mandatory, you can just let it go out of scope. When you do want to invalidate it just do:

self.observation?.invalidate()

Upvotes: 1

Amrit Sidhu
Amrit Sidhu

Reputation: 1950

I have figured out the issue. Actually the concern was that I used removeObserver(self, forKeyPath: "myLocation", context: nil) instead of mapView.removeObserver(self, forKeyPath: "myLocation", context: nil)

Upvotes: 0

Related Questions