I am using MapKit
and have a map with custom annotations
, that normally works okay. But at some moment the app crashes at the map screen and the information in the stacktrace and the device logs is insufficient for me to find the cause. This is what I get in Xcode:
And this is from the device logs:
Turning Zombies on results in the following message on crash: *** -[MapView respondsToSelector:]: message sent to deallocated instance 0x12286afd0
So this means that MapView object gets deallocated at some point, but this is very weird since the view is present.
Some code of MapView implementation:
@interface MapView () <MKMapViewDelegate, CLLocationManagerDelegate>
@property (strong, nonatomic) NSArray *cameras;
@property (strong, nonatomic) NSMutableArray *tapGestureRecognizers;
@end
@implementation MapView
#pragma mark - Init
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
self.tapGestureRecognizers = [[NSMutableArray alloc] init];
self.backgroundColor = [UIColor clearColor];
[LocationManager sharedClient].delegate = self;
self.mapView = [[MKMapView alloc] initWithFrame:self.bounds];
[self addSubview:self.mapView];
self.mapView.tintColor = [UIColor xSelfiePink];
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:0];
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.mapView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
[self addConstraint:leftConstraint];
[self addConstraint:rightConstraint];
[self addConstraint:topConstraint];
[self addConstraint:bottomConstraint];
self.translatesAutoresizingMaskIntoConstraints = NO;
self.mapView.translatesAutoresizingMaskIntoConstraints = NO;
self.mapView.delegate = self;
self.mapView.mapType = MKMapTypeStandard;
[self.mapView setUserTrackingMode:MKUserTrackingModeFollow animated:YES];
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(openCamera:) name:kRegionNotificationActionOpenCamera object:nil];
[CameraManager getCamerasWithCompletion:^(NSArray *cameras, NSError *error) {
if (error) {
if (self.delegate && [self.delegate respondsToSelector:@selector(presentError:)]) {
[self.delegate presentError:error];
}
return;
}
self.cameras = cameras;
[self.mapView addAnnotations:cameras];
for (Camera *cam in cameras) {
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:cam.coordinate radius:500 identifier:cam.name];
[[LocationManager sharedClient] startMonitoringForRegion:region];
}
}];
}
return self;
}
#pragma mark - MKMapViewDelegate Methods
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[Camera class]]) {
Camera *camera = annotation;
CameraAnnotation *annotationView = (CameraAnnotation *) [mapView dequeueReusableAnnotationViewWithIdentifier:placemarkIdentifier];
if (!annotationView) {
annotationView = [[CameraAnnotation alloc] initWithCamera:camera];
annotationView.cameraAnnotationDelegate = self.cameraAnnotationDelegate;
}
else {
annotationView.annotation = annotation;
}
annotationView.camera = camera;
if (camera.status == Inactive) {
annotationView.rightCalloutAccessoryView = nil;
}
return annotationView;
}
return nil;
}
- (void)showUser {
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(self.mapView.userLocation.location.coordinate, 1000, 1000);
[self.mapView setRegion:[self.mapView regionThatFits:viewRegion] animated:YES];
}
- (void)centerMapOnCameraWithCoordinate:(CLLocationCoordinate2D)coordinate {
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(coordinate, 500, 500);
[self.mapView setRegion:[self.mapView regionThatFits:viewRegion] animated:YES];
}
The MapView instance
is an outlet
in the view controllers
where it is used. This is not the whole implementation but the crash happens with or without the rest commented out so no need to add it.
Results from puttingthe following in a dealloc method: NSLog(@"%@ deallocated because %@", self, [NSThread callStackSymbols]);