3

I am writing you because I am stuck with a super strange error. I tried to add GMS on my app, and finally, when I have to get device location, I am stuck with this crash:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance 0x7ff7fd82def0 of class GMSMapView was deallocated while key value observers were still registered with it. Current observation info: ( Context: 0x0, Property: 0x7ff7fdc2f470>

Code is initialized here:

self.mapView.myLocationEnabled = YES;
self.mapView.mapType = kGMSTypeNormal;
self.mapView.settings.compassButton = YES;
self.mapView.settings.myLocationButton = YES;

//=>    Listen to the myLocation property of GMSMapView.
[self.mapView addObserver:self
               forKeyPath:@"myLocation"
                  options:NSKeyValueObservingOptionNew
                  context:NULL];


- (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary *)change
                   context:(void *)context
{
if ([keyPath isEqualToString:@"myLocation"] && [object isKindOfClass:[GMSMapView class]])
{   
    appDelegate().curUserLocation = [change objectForKey:NSKeyValueChangeNewKey];

    [self.mapView animateToCameraPosition:[GMSCameraPosition cameraWithLatitude:self.mapView.myLocation.coordinate.latitude
                                                                             longitude:self.mapView.myLocation.coordinate.longitude
                                                                                  zoom:15]];
}
}

and still no success. I put breakpoint in observerValueForKey method, and once is out from here, crash appears. No way to get the idea.

I also removed observer :

- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];

[self.mapView removeObserver:self forKeyPath:@"myLocation"];

//=>    Set map delegate to nil (to avoid:   mapView:regionDidChangeAnimated:]: message sent to deallocated instance )
self.mapView.delegate = nil;
self.mapView = nil;
}

and no success.

Can anyone help me with this ? I tried all possible solutions, but no way.

Thanks in advance!

Bonnke
  • 896
  • 1
  • 12
  • 24
  • maybe the GMSMapView property it is not set to `strong`.. like this `@property (nonatomic, strong) GMSMapView *mapView`? – TonyMkenu Nov 28 '14 at 22:32
  • I set it to WEAK, because it is IBOutlet @property (weak, nonatomic) IBOutlet GMSMapView *mapView; – Bonnke Nov 29 '14 at 08:08
  • @TonyMkenu yeah... I change it to '@property (strong) IBOutlet GMSMapView *mapView;' and no crash now... But map is not visible . It is hiding after 1 second. And 'observeValueForKeyPath:' is not called now :? – Bonnke Nov 29 '14 at 08:22
  • Then, you have some issues with GMSMap, maybe now it is not right connected to your IBOutlet – TonyMkenu Nov 29 '14 at 09:54
  • @TonyMkenu I just added an UIView, then subclassed to GMSMapView, then connected IBOutlet. Nothing else. – Bonnke Nov 29 '14 at 10:13

2 Answers2

2

How already said in comment.. the GMSMapView must be Strong Your code will not work in iOS 8 if you not call requestWhenInUseAuthorization

I recommend you to use only the CLLocationManager instead KVO... but is your decision.

Attached my example - I modified the Google example... with 2 example:

  1. with KVO
  2. only with CLLocationManager

If you have any issues... just let me know

PS Don't forget to add you API Key

Happy coding!

UPDATE

if you startUpdatingLocation.. don't forget to stop it somewhere with stopUpdatingLocation.. let say in ViewDidDisapear

TonyMkenu
  • 7,597
  • 3
  • 27
  • 49
  • Hi Man... many many thanks for your effort . And YES, that was my temporary decision. I totally removed KVO, and worked with CLLocationManager. Things are ok now. But need to investigate more. Many many thanks for your time... – Bonnke Nov 29 '14 at 23:17
2

If you register inside viewWillAppear:, use viewWillDisappear to remove observer.

If you register inside viewDidLoad, use deinit to unregister the observer. Always use the counter part to register and unregister and that should be fine

Swift 3

deinit {
     mapView.removeObserver(self, forKeyPath: "myLocation")
}
Sourabh Sharma
  • 8,222
  • 5
  • 68
  • 78