MKMapView crashing if zooming while adding annotations

有些话、适合烂在心里 提交于 2020-06-26 16:43:10

问题


It looks like I'm running into an issue where I can reliably cause my MKMapView to crash if I'm adding annotations while the map's visible region is being changed. I've boiled the code that is causing it down to a pretty simple implementation, and I'm reproducing it here:

NSMutableArray *pointAnnotationArray = [[NSMutableArray alloc] init];
MKCoordinateRegion coordRegion = [mapViewOutlet region];
float randMax = 0.1;

for (int i = 0; i < 100; i++){
    float randomDeviation1 =  (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * randMax) - (randMax / 2);
    float randomDeviation2 =  (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * randMax) - (randMax / 2);

    MKPointAnnotation *point = [[MKPointAnnotation alloc] init];        
    CLLocationCoordinate2D pointLocation = CLLocationCoordinate2DMake(coordRegion.center.latitude + randomDeviation1, coordRegion.center.longitude + randomDeviation2);
    [point setCoordinate:pointLocation];    
    [pointAnnotationArray addObject: point];
}

[mapViewOutlet addAnnotations:[NSArray arrayWithArray:pointAnnotationArray]];

What I'm doing above is adding 100 points on the map that are distributed randomly (enough) in and around the MKMapView's visible region. The easiest way to reproduce this is to set this code to run on a timer (say after 5 seconds), then grab the map and start zooming in and out a bit until the timer's run. Once you get a feel for it you can get a crash every time. Disabling user interaction on mapViewOutlet before the addAnnotations call doesn't seem to help. (Perhaps it isn't able to disable user interaction while the user is mid-gesture, which is understandable I suppose.)

My other problem is that I'm not having much luck tracing the crash – I don't have a lot of experience causing crashes that aren't happening directly in my own code, so I might be missing out on some obvious way to trace it, but I'm currently getting an unhelpful breakpoint on the return UIApplicationMain line in main.m. My best guess is that we're causing some issues with how the MKMapView only draws visible annotations – the zooming is causing that visible region to change, while annotations are being added and the map is trying to determine which points to draw.

Has anyone else seen this? Any suggestions on how to avoid it, without locking my map down from user interaction for some significant length of time on either end of my annotation addition?

Edit: Forgot to include the call stack:

#0  0x3752a944 in objc_exception_throw ()
#1  0x3869dec0 in __NSFastEnumerationMutationHandler ()
#2  0x31929d46 in -[MKAnnotationContainerView _updateAnnotationViewPerspective] ()
#3  0x3192981a in -[MKMapView _updateScrollContainerView:] ()
#4  0x3192ff66 in -[MKMapView mapViewDidDraw:] ()
#5  0x391560b4 in -[VKMapCanvas didDrawView] ()
#6  0x3914d4a8 in -[VKScreenCanvas onTimerFired:] ()
#7  0x3914b4a8 in -[VKMapCanvas onTimerFired:] ()
#8  0x3914a346 in -[VKMainLoop displayTimerFired:] ()
#9  0x35ebe780 in CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long) ()
#10 0x35ebe6d8 in CA::Display::IOMFBDisplayLink::callback(__IOMobileFramebuffer*, unsigned long long, unsigned long long, unsigned long long, void*) ()
#11 0x34815fd6 in IOMobileFramebufferVsyncNotifyFunc ()
#12 0x370315ac in IODispatchCalloutFromCFMessage ()
#13 0x3866888a in __CFMachPortPerform ()
#14 0x386733e6 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#15 0x3867338a in __CFRunLoopDoSource1 ()
#16 0x3867220e in __CFRunLoopRun ()
#17 0x385e523c in CFRunLoopRunSpecific ()
#18 0x385e50c8 in CFRunLoopRunInMode ()
#19 0x3591e33a in GSEventRunModal ()
#20 0x379d5290 in UIApplicationMain ()
#21 0x0005aff4 in main at /Users/Sydin/App/main.m:16

回答1:


It looks like some kind of problem with changes to the visible annotations while you're adding new ones — probably a problem in MKMapView, since it's probably doing its updates in a secondary thread (it's finicky like that). What I would do is respond to the following two MKMapViewDelegate methods:

  • mapView:regionWillChangeAnimated:
  • mapView:regionDidChangeAnimated:

In the first, set a flag that designates the map as being moved by the user to YES. In the second, set the flag to NO. Then, whenever you want to add new annotations, check the flag. If it's NO, then you're fine to update immediately. If it's YES, add your annotations to a mutable set. In mapView:regionDidChangeAnimated:, add any annotations in that set to the map view before emptying the set.

This should fix the problem, even if it's not an elegant solution. You can open the breakpoint pane in Xcode and click the add button, then select "Exception Breakpoint" so that when your app crashes, you get the exact line instead of main.m.




回答2:


I had a similar issue where i was adding a group of annotations fetching from my server and converting them from json to nsarray but because this was done in the background thread when adding and removing to mapview i had NSGenericException , my solution was doing add remove operation on the main thread like below and all is working , even when user is zooming in out you can add remove annotations.But there will be slight delay while adding because i am trying like 1k to 2k sized array. For smaller stuff should be alright.

 dispatch_async(dispatch_get_main_queue(),
 ^{
        [self.mapView removeAnnotations:self.mapView.annotations];
        [self.mapView addAnnotations:tempNSArray];

    });


来源:https://stackoverflow.com/questions/13924130/mkmapview-crashing-if-zooming-while-adding-annotations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!