1

I met across one bug. I use OSM tiles in my map because they display my location better. So, my viewDidLoad is:

[super viewDidLoad];

self.mapView.delegate =  self;
self.searchBar.delegate = self;
self.title = @"Select Location";
NSString *template = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";
MKTileOverlay *overlay = [[MKTileOverlay alloc] initWithURLTemplate:template];
overlay.canReplaceMapContent = YES;
[self.mapView addOverlay:overlay level:MKOverlayLevelAboveLabels];

self.locationManager = [[CLLocationManager alloc] init];
if ( [CLLocationManager locationServicesEnabled] ) {
    self.locationManager.delegate = self;
    self.locationManager.distanceFilter = 1000;
    [self.locationManager startUpdatingLocation];
}

self.geocoder = [[CLGeocoder alloc] init];
...

Well, the bug appears, when I try to press Back or select the current location pin (I have a UIButton on it, before all the tiles for the view are loaded.

I've checked this question. And added this:

- (void)viewWillDisappear:(BOOL)animated {
self.mapView = nil;
[super viewWillDisappear:animated];
}

I tried to use this code in both viewWillDisappear and dealloc, but neither seem to work. Next, I've overridden back button action and still having this issue:

- (void)viewWillDisappear:(BOOL)animated {
if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) {
    self.locationManager.delegate = nil;
    self.mapView =  nil;
    self.searchBar.delegate = nil;
    [self.navigationController popViewControllerAnimated:YES];
}
[super viewWillDisappear:animated];
}

EXC_BAD_ACCESS usually appears, when something tries to access the object, when it has a;ready been deallocated, as far as I know.

How can I properly dealloc all the data?

UPD: The exception appears on line: return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

It appears in the first thread:

libobjc.A.dylib`objc_msgSend:
0x3b172620:  cbz    r0, 0x3b17265e            ; objc_msgSend + 62
0x3b172622:  ldr.w  r9, [r0]
0x3b172626:  ldrh.w r12, [r9, #12] <<<< Here

And finally here in UIApplicationMain

 0x3316e148:  blx    0x33731cc4                ; symbol stub for: CFRunLoopSourceSignal$shim
 0x3316e14c:  movs   r0, #0x0 <<< This line

UPD2: Well, running with zombies on simulator and examining stack showed such things: stack

As far as I understand, the problem appears, when MKTileOverlay tries to load tiles on deallocated MapView. How this can be fixed?

Community
  • 1
  • 1
vladfau
  • 1,003
  • 11
  • 22
  • do you use arc for memory management? – Daij-Djan Jul 21 '14 at 21:39
  • use instruments with zombies tool and figure out WHICH class is accessed?! – Daij-Djan Jul 21 '14 at 21:40
  • @Daij-Djan what if I can't run it in the simulator (due to using parse.com iOS API and multiple linker errors on Mac)? – vladfau Jul 21 '14 at 21:48
  • @Daij-Djan well, I've cleaned up the mess with dependencies. Now will try to catch zombies – vladfau Jul 21 '14 at 21:59
  • @ka2m You're exception backtrace is useless. You need to create an exception breakpoint. Please read the article [My App Crashed, Now What?](http://www.raywenderlich.com/10209/my-app-crashed-now-what-part-1) which is also referenced in the ios-tag-wiki (because I have put it there a few weeks ago.) Every exception appears to be on the line `return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));` if you don't use the debugger properly, so it doesn't provide any new insights. – Michael Jul 21 '14 at 21:59
  • @Michael an exception breakpoint is useless with signals AFAIK. still you are right that the OPs report is meaningless – Daij-Djan Jul 21 '14 at 22:02
  • @Daij-Djan well, the post says "The exception appears on line ...", so I think it's an exception. Furthermore, I have never seen an EXC_BAD_ACCESS on "main.m", but I see exceptions thrown on main.m all the time (because of the missing exception breakpoint). – Michael Jul 21 '14 at 22:11
  • @Michael You are wrong on both accounts im afraid. but lets see what the OP digs up – Daij-Djan Jul 21 '14 at 22:17

1 Answers1

1

Well, it seems that I've found the solution.

The origin is from here.

I've made two fixes. First of all, I moved all the tile processing to async block:

dispatch_async(dispatch_get_main_queue(), ^{
    NSString *template = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png";
    MKTileOverlay *overlay = [[MKTileOverlay alloc] initWithURLTemplate:template];
    overlay.canReplaceMapContent = YES;
    [self.mapView addOverlay:overlay level:MKOverlayLevelAboveLabels];});

Next, I added this line to dealloc and removed viewWillDisappear:

- (void)dealloc 
{
    [self.mapView removeOverlays:[self.mapView overlays]];
}

Now it seems to work.

Community
  • 1
  • 1
vladfau
  • 1,003
  • 11
  • 22