2

I've a simply view controller with a MKMapView object inside, defined in this way:

Class declaration:

@interface GeoViewController : UIViewController  <MKMapViewDelegate>

@property (nonatomic, strong) MKMapView* viewMap;

@end

Implementation:

@implementation GeoViewController

- viewDidAppear:(BOOL)animated  {
    [super viewDidAppear:animated]; 
    viewMap = [[MKMapView alloc] init];
    MKCoordinateRegion worldRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);
    [viewMap setRegion:worldRegion animated:YES];
    viewMap.pitchEnabled = YES;
    viewMap.showsUserLocation = YES;
    viewMap.delegate = self;
    [self.view addSubview:viewMap];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    viewMap.showsUserLocation = NO;
    self.viewMap.delegate = nil;
    [self.viewMap removeFromSuperview];
}

- (void)resizeForOrientation:(BOOL)isLandscape withFrame:(CGRect)frame {
    [super resizeForOrientation:isLandscape withFrame:frame];
    const CGRect fullFrame = CGRectMake(0, 0, frame.size.width, frame.size.height);
    viewMap.frame = fullFrame;
}

@end

First time that I present the view controller works. Then I navigate in my app and if I come back on GeoViewController, crash:

  • no message error on console
  • main.m is opened and report "Thread 1: EXC_BAD_ACCESS"
  • on debug navigator (left) I get error report on Thread 1:

    EAGLContext_renderbufferStorageFromDrawable(EAGLContext*, objc_selector*, unsigned int, id)

Now, googling a lot, I can't find a working solution for me:

I also try on viewDidDisappear, but no way

 [EAGLContext setCurrentContext:nil];

Seems crashing for this row:

 viewMap.frame = fullFrame;

Any suggestion will be appreciated!

update

I receive other errors sometime in my test:

opengl thread conflict detected

Luca Davanzo
  • 21,000
  • 15
  • 120
  • 146
  • May be unrelated but since `viewMap` is a property, you should assign it using `self.viewMap = ...` instead of just `viewMap = ...`. So `viewMap = [[MKMapView alloc] init];` should be `self.viewMap = [[MKMapView alloc] init];`. –  May 23 '15 at 12:18

4 Answers4

4

I got EXC_ARM_DA_ALIGN Errors in

EAGLContext_renderbufferStorageFromDrawable(EAGLContext*, objc_selector*, unsigned int, id)

aswell, when using a MKMapView.

The Workaround mentioned in this Question: Adding google maps as subview crashes iOS app with exc_bad worked for me.

Disableling "GPU Frame Capture" feature in my target schemes did the trick.

Community
  • 1
  • 1
qRis
  • 86
  • 6
2

Product -> Edit Scheme -> Run -> Options -> Set GPU Frame Capture to Disabled.

Refetence Link

Community
  • 1
  • 1
Milap Kundalia
  • 1,566
  • 1
  • 16
  • 24
0

I think this line is the one causing the problem

[self.viewMap removeFromSuperview];

Because if you said that you just navigated back to the view, the viewDidLoad will not be called again. That's why it said that "Thread 1: EXC_BAD_ACCESS", because your accessing a released object. It crashes on the viewMap.frame = frame because you are accessing the viewMap object which is already released because you remove it from its superView.

John Russel Usi
  • 453
  • 3
  • 13
0

viewDidAppear is called when you push your controller on and also when it has another controller pushed on top. Hence at the moment when you navigate, you are removing the map. The same applies to viewWillDisappear as it will be called when you push a new controller on top and also when you finally pop your controller off.

Simply change your functions to add the map when the controller first appears and only do the remove when the controller is being popped from the navigation controller. Something like:

- viewDidAppear:(BOOL)animated  {
    [super viewDidAppear:animated]; 

    if (self.isMovingToParentViewController){
      viewMap = [[MKMapView alloc] init];
      MKCoordinateRegion worldRegion = MKCoordinateRegionForMapRect(MKMapRectWorld);
      [viewMap setRegion:worldRegion animated:YES];
      viewMap.pitchEnabled = YES;
      viewMap.showsUserLocation = YES;
      viewMap.delegate = self;
      [self.view addSubview:viewMap];
  }
}

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

  // If being popped off, remove the map view. Otherwise
  // leave it alone as we need it when the user navigates
  // back
  if (self.isMovingFromParentViewController){
    viewMap.showsUserLocation = NO;
    self.viewMap.delegate = nil;
    [self.viewMap removeFromSuperview];
  }
}

}

This makes sure that the map is present for the duration of the lifetime of the controller which should make sure any access to it is valid at all times.

Rory McKinnel
  • 7,936
  • 2
  • 17
  • 28
  • @Velthune I noticed you edited your question and moved the map create to `viewDidAppear`. You should also put a guard around that so you only create when the controller is first pushed. See updated answer. If you add/remove all the time there is a period where you may have no map. So create it on first show and remove it when popped off as shown in updated answer. – Rory McKinnel May 22 '15 at 10:07