0

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:

Xcode error

And this is from the device logs:

enter image description here

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]);

enter image description here

surToTheW
  • 772
  • 2
  • 10
  • 34
  • You should add an Exception Breakpoint to get better information about the crash. [Check out this question.](https://stackoverflow.com/q/17802662/3151675) – Tamás Sengel Mar 26 '18 at 13:44
  • @the4kman Thanks. I added one, but it's not being raised and I don't get any info from it. – surToTheW Mar 26 '18 at 13:45
  • objc_msgSend is commonly due to memory management problems (trying to send a message to an object that has been deleted). Try turning on Zombies in your build scheme to see if you get better information. – Phillip Mills Mar 26 '18 at 14:11
  • @PhillipMills Thank you, turning on Zombies gives me more information : *** -[MapView respondsToSelector:]: message sent to deallocated instance 0x12286afd0 I am still not clear how it gets deallocated – surToTheW Mar 27 '18 at 08:36
  • Options: Add some code showing how you use a MapView or run Instruments with the Allocations tool and see the retain/release history of the object. – Phillip Mills Mar 27 '18 at 12:16
  • @PhillipMills I added some code. Also looked at the Allocations tool, but couldn't get where the issue comes from. – surToTheW Mar 27 '18 at 13:52
  • Try putting the following in a `dealloc` method: `NSLog(@"%@ deallocated because %@", self, [NSThread callStackSymbols]);`. It should show you a trace at the point the object becomes invalid. (Needs to run without Zombies enabled.) – Phillip Mills Mar 27 '18 at 14:05
  • Concerning the code, the problem is more likely to be how a `MapView` is used rather than how it's implemented. – Phillip Mills Mar 27 '18 at 14:06
  • @PhillipMills I updated my question with the results from putting [NSThread callStackSymbols] in dealloc. I couldn't trace the issue from there though. I will also add some info how the map view is used. – surToTheW Mar 27 '18 at 14:15
  • The mention of "autorelease" in the stack trace just suggests that the variable holding the `MapView` went out of scope. Do you do anything odd with the view controller that owns the `MapView` (like showing its view as a subview in some other controller)? – Phillip Mills Mar 27 '18 at 14:18
  • @PhillipMills Not completely sure, it is not my code. but I not as far as I see. But continuing looking. MapView usage to reproduce the issue is the following. Have the MapView as a subview in the view of a ViewController. Go to this view controller and leave it very fast. The app will crash (not every time though) after a second or two with the statement that the map view is deallocated. No additional code is needed to reproduce the issue, just setting the MapView in storyboard. – surToTheW Mar 27 '18 at 14:26
  • Running out of ideas.... In a `dealloc` method for `MapView`, try `self.mapView.delegate = nil;`. – Phillip Mills Mar 27 '18 at 15:11
  • @PhillipMills Thank you for your suggestions. There was a CLLocationManager subclass that had the view as its delegate. I set it to nil in dealloc and for now it seems to have solved it. Please put your last suggestions in an answer so I can credit you. – surToTheW Mar 28 '18 at 12:24

0 Answers0