MKMarkerAnnotationViews with clustering: MapKit crash when zooming/panning

I have a MapView with many MKMarkerAnnotationViews (about 300). iOS 11 clustering support enabled. After some scrolling and zooming through the MapView my app crashes because MapKit crashes.


When I see the crashlog I am sure this is not a crash in my code but in MapKit itself. Do you think this estimation is correct? Does anyone see this crash too?


This is the crashlog:


Last Exception Backtrace:
0   CoreFoundation                 0x186f4bd38 __exceptionPreprocess + 124
1   libobjc.A.dylib               0x186460528 objc_exception_throw + 55
2   CoreFoundation                 0x186ee4c44 _CFThrowFormattedException + 111
3   CoreFoundation                 0x186e19ff4 -[__NSDictionaryM setObject:forKey:] + 855
4   MapKit                         0x197329930 -[MKNewAnnotationContainerView _existingClusterViewsForClusterID:] + 171
5   MapKit                         0x1973291ec -[MKNewAnnotationContainerView addAnnotationView:allowAnimation:] + 171
6   MapKit                         0x1972b9040 -[MKMapView addAnnotationRepresentation:allowAnimation:] + 687
7   MapKit                         0x197277d14 -[MKAnnotationManager _addRepresentationForAnnotation:] + 843
8   MapKit                         0x19729b63c -[MKAnnotationManager addRepresentationsForAnnotations:] + 351
9   MapKit                         0x1972b1f7c -[MKMapView annotationContainer:requestAddingClusterForAnnotationViews:] + 631
10  MapKit                         0x197329ad8 -[MKNewAnnotationContainerView _updateClusterableAnnotationViews:withID:] + 395
11  CoreFoundation                 0x186e1a6cc -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 231
12  MapKit                         0x19732a698 -[MKNewAnnotationContainerView updateAnnotationViewsForReason:] + 295
13  MapKit                         0x197279cfc -[MKAnnotationContainerView finishAddingAnnotationViews] + 31
14  MapKit                         0x1972b9658 -[MKMapView annotationManager:didAddAnnotationRepresentations:] + 59
15  MapKit                         0x1972769b0 -[MKAnnotationManager updateVisibleAnnotations] + 1491
16  MapKit                         0x197291620 -[MKMapView _didChangeRegionMidstream:] + 243
17  MapKit                         0x1972addf0 -[MKMapView mapLayer:didChangeRegionAnimated:] + 71
18  VectorKit                     0x196c60690 -[VKMapView map:didChangeRegionAnimated:] + 143
19  MapKit                         0x197321430 -[MKMapGestureController _handleStandardPan:] + 1579
20  MapKit                         0x197295cfc -[MKMapGestureController handlePan:] + 19
21  UIKit                         0x1909e7f78 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 63
22  UIKit                         0x1909ec4dc _UIGestureRecognizerSendTargetActions + 123
23  UIKit                         0x1904d6dc8 _UIGestureRecognizerSendActions + 319
24  UIKit                         0x19038b748 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 731
25  UIKit                         0x1909d63fc _UIGestureEnvironmentUpdate + 1055
26  UIKit                         0x1909d5f88 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 403
27  UIKit                         0x1909d50e4 -[UIGestureEnvironment _updateGesturesForEvent:window:] + 275
28  UIKit                         0x190389a54 -[UIWindow sendEvent:] + 3179
29  UIKit                         0x19035b078 -[UIApplication sendEvent:] + 339
30  UIKit                         0x190c9af98 __dispatchPreprocessedEventFromEventQueue + 2363
31  UIKit                         0x190c9d408 __handleEventQueueInternal + 4759
32  UIKit                         0x190c96574 __handleHIDEventFetcherDrain + 151
33  CoreFoundation                 0x186ef4358 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 23
34  CoreFoundation                 0x186ef42d8 __CFRunLoopDoSource0 + 87
35  CoreFoundation                 0x186ef3b60 __CFRunLoopDoSources0 + 203
36  CoreFoundation                 0x186ef1738 __CFRunLoopRun + 1047
37  CoreFoundation                 0x186e122d8 CFRunLoopRunSpecific + 435
38  GraphicsServices               0x188ca3f84 GSEventRunModal + 99
39  UIKit                         0x1903be880 UIApplicationMain + 207
40  Bookshelf                     0x10086ce14 0x100850000 + 118292
41  libdyld.dylib                 0x18693656c start + 3



This happens on a iPhone 5s with iOS 11. I can reproduce this for all iOS 11 releases including the current ios 11.1 beta 2.

Accepted Reply

Hllo everybody, i find solutions.

At first - it s..t happens when we use

mapView.register(AnyClass?, forAnnotationViewWithReuseIdentifier: String)

and

mapView.dequeueReusableAnnotationView(withIdentifier: String)

- return nil.

So hot fix:

Add:

ViewController: UIViewController, MKMapViewDelegate

add

    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.delegate = self

        mapView.register(MarkerPointView.self, forAnnotationViewWithReuseIdentifier: "marker")
        mapView.register(ClusterView.self, forAnnotationViewWithReuseIdentifier: "cluster")
}

and finaly:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        if let marker = annotation as? MarkerAnnotation{
            var view = mapView.dequeueReusableAnnotationView(withIdentifier: "marker") as? MarkerPointView
            if view == nil {
//Very IMPORTANT
                print("nil for Marker")
                view = MarkerPointView(annotation: marker, reuseIdentifier: "marker")
            }
            return view
        }else if let cluster = annotation as? MKClusterAnnotation{
            var view = mapView.dequeueReusableAnnotationView(withIdentifier: "cluster") as? ClusterView
            if view == nil{
//Very IMPORTANT
                print("nil for Cluster")
                view = ClusterView(annotation: cluster, reuseIdentifier: "cluster")
            }
            return view
        }
        else{
            return nil
        }
    }



hope it's help for somebody, and on next revs apple fix it, because we can use it like they said on wwdc2017 on 36:50 - we CAN'T delete it!!!!!!!!

Replies

I have the same issue with my project


I thought it was some code of mine, but i've tried to run the WWDC17 "What's New in MapKit" Session's Sample code and the exact same crash happens

Thank you for your reply. Good to hear I am not alone with this issue. I already reported this as a bug to Apple two weeks ago but have not heard back from them since.

yes, my radar has been updated with reference to other duplicated radar!


have you find a workaround?

I could not find any workaround yet.

Any fix founded ?

Since last week I'm trying to use the new clustering system.

But got the exact same crash, even with the Tandm demo that Apple' provide.

Hllo everybody, i find solutions.

At first - it s..t happens when we use

mapView.register(AnyClass?, forAnnotationViewWithReuseIdentifier: String)

and

mapView.dequeueReusableAnnotationView(withIdentifier: String)

- return nil.

So hot fix:

Add:

ViewController: UIViewController, MKMapViewDelegate

add

    override func viewDidLoad() {
        super.viewDidLoad()
        mapView.delegate = self

        mapView.register(MarkerPointView.self, forAnnotationViewWithReuseIdentifier: "marker")
        mapView.register(ClusterView.self, forAnnotationViewWithReuseIdentifier: "cluster")
}

and finaly:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        if let marker = annotation as? MarkerAnnotation{
            var view = mapView.dequeueReusableAnnotationView(withIdentifier: "marker") as? MarkerPointView
            if view == nil {
//Very IMPORTANT
                print("nil for Marker")
                view = MarkerPointView(annotation: marker, reuseIdentifier: "marker")
            }
            return view
        }else if let cluster = annotation as? MKClusterAnnotation{
            var view = mapView.dequeueReusableAnnotationView(withIdentifier: "cluster") as? ClusterView
            if view == nil{
//Very IMPORTANT
                print("nil for Cluster")
                view = ClusterView(annotation: cluster, reuseIdentifier: "cluster")
            }
            return view
        }
        else{
            return nil
        }
    }



hope it's help for somebody, and on next revs apple fix it, because we can use it like they said on wwdc2017 on 36:50 - we CAN'T delete it!!!!!!!!

I can't tell how much it will help ! Thank you so much !

**** finally ! I was on it since 3 days ! Trying to find a way to check everything in details. I was about to give up !

Thank you !

never give up! 🙂

I'm glad It helped for you

Thank you a lot! This works as a workaround for me too!


In viewDidLoad() I have


mapView.register(BookshelfAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)


And then I added


    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKClusterAnnotation {
            return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier, for: annotation)
        } else if annotation is BookshelfAnnotation {
            return mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier, for: annotation)
        } else {
            return nil
        }
    }


I use the default view for cluster annotations. BookshelfAnnotation is my custom subclass of MKPointAnnotation.


Even though this works fine as a workaround everyone following this thread should report this as a bug to Apple because they say in WWDC17 we can remove the delegate function. However this causes this crash.

🙂 thanks a lot, i was looking for a solution from 3 days 🙂

Thanks for the patch everyone—fantastic work!

This was a really difficult bug to track down!

Apple replied to my bug report and says this issue should be fixed in iOS 11.2 beta 1. I have not verified this yet.

ty, will check on 11.2 but not not beta.

It still does not work for me

This is my error :

This is the error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[1]'

*** First throw call stack:

(0x18525ed8c 0x1844185ec 0x1851f7750 0x18512aa18 0x19621fbcc 0x1960b0e40 0x196128ee8 0x18512d3a0 0x196129ab8 0x1961f8e54 0x196075eac 0x185cab3d4 0x185207aa8 0x18520776c 0x185207010 0x185204b60 0x185124da8 0x187109020 0x18f141758 0x10430352c 0x184bb5fc0)

libc++abi.dylib: terminating with uncaught exception of type NSException





**I follow this example:**



https://developer.apple.com/videos/play/wwdc2017/237/



This example also crashed when you put 100 markers



Help please