In MKMapView, show (some) annotations only when zoomed in

I have a UIKit app with an MKMapview. In that mapview, I show icons on the location of Airfields. When zooming out to Europe (or USA for that matter), the whole map is covered with the annotations, so I want to only show these annotations when zoomed in beyond some level.

How can that be achieved?

I did find a way like this:

class MapViewController: UIViewController {

var isAtBigZoom = true {
        didSet {
            guard oldValue != isAtBigZoom else {
                return
            }

            for case let annot in mapView.annotations {
                mapView.view(for: annot)?.alpha = isAtBigZoom ? 1 : 0
            }
        }
    }
}

extension MapViewController: MKMapViewDelegate {
    
    func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
        isAtBigZoom = mapView.region.span.latitudeDelta < self.airportThreshold
    }
 }

But I have 2 problems with that:

  1. Seems like a lot of processing power
  2. It only takes effect after a pan. So I zoom beyond the limit, alpha has the 'old' value. Only after I pan, the alpha is suddenly represented in the MapView.

Does anybody know a better solution?

Answered by DTS Engineer in 798995022

Have you considered clustering the annotations instead of removing them? It's an API in MapKit with a sample code project.

— Ed Ford,  DTS Engineer

Accepted Answer

Have you considered clustering the annotations instead of removing them? It's an API in MapKit with a sample code project.

— Ed Ford,  DTS Engineer

Hi Ed, I actually did, and it works!! It is not exactly what I wanted, but it is much clearer now! Thanks! Wouter

Hi, Like I said, I did use the clustering.

This works very simple: Just add the following line:

annotationView?.clusteringIdentifier = "Shop"

and all shops will be grouped together.

However, when panning, now I often get:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MKPointAnnotation memberAnnotations]: unrecognized selector 

I tried many things, but in the stack trace, I get no functions that I built.

I never (or rarely) see this haoppen when I have like 200 annotations that I need to group (with only one clustering identifier)

But when I have a larger area, with say 2000 annotations (with only one clustering identifier) I do get the crash.

Does anybody know what is happening? And how I can stop the app from crashing?

I am writing this:

  • In Swift
  • Using xcode Version 15.4 (15F31d)
  • On a Mac Studio
  • On an iPhone 14, and when running on 'Mac (designed for iPad)"

Crash log:

-[MKPointAnnotation memberAnnotations]: unrecognized selector sent to instance 0x60000335f800
(
	0   CoreFoundation                      0x000000019928e2ec __exceptionPreprocess + 176
	1   libobjc.A.dylib                     0x0000000198d72158 objc_exception_throw + 60
	2   CoreFoundation                      0x000000019934056c -[NSObject(NSObject) __retain_OA] + 0
	3   CoreFoundation                      0x00000001991f7f3c ___forwarding___ + 1580
	4   CoreFoundation                      0x00000001991f7850 _CF_forwarding_prep_0 + 96
	5   MapKit                              0x00000001dd39c268 -[MKMapView annotationContainer:requestAddingClusterForAnnotationViews:] + 120
	6   MapKit                              0x00000001dd4f916c -[MKAnnotationContainerView _updateClusterableAnnotationViews:withID:] + 284
	7   CoreFoundation                      0x00000001991db934 __NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ + 24
	8   CoreFoundation                      0x000000019921b2ec -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 288
	9   MapKit                              0x00000001dd4f6510 -[MKAnnotationContainerView _updateAnnotationViewsForReason:updatePositions:] + 552
	10  MapKit                              0x00000001dd4f7ec8 -[MKAnnotationContainerView finishAddingAndRemovingAnnotationViews] + 28
	11  MapKit                              0x00000001dd439f98 -[MKAnnotationManager updateVisibleAnnotations] + 888
	12  MapKit                              0x00000001dd39267c -[MKMapView _didChangeRegionMidstream:] + 220
	13  MapKit                              0x00000001dd39a8fc -[MKMapView mapLayerDidChangeRegionAnimated:] + 60
	14  VectorKit                           0x00000001ccd76b24 -[VKCameraDelegateMediator mapLayerDidChangeRegionAnimated:] + 132
	15  VectorKit                           0x00000001ccd76a6c -[VKCameraController endRegionChange] + 80
	16  VectorKit                           0x00000001cd42b528 -[VKScreenCameraController stopPinchingWithFocusPoint:] + 64
	17  VectorKit                           0x00000001cce142b8 -[VKMapView stopPinchingWithFocusPoint:] + 104
	18  MapKit                              0x00000001dd41082c -[MKMapGestureController _updateZoomGestureForState:focusPoint:scale:velocity:gestureType:configuration:] + 824
	19  MapKit                              0x00000001dd41028c -[MKMapGestureController handlePinch:] + 312
	20  UIKitCore                           0x00000001c88c7700 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 124
	21  UIKitCore                           0x00000001c88c7574 _UIGestureRecognizerSendTargetActions + 92
	22  UIKitCore                           0x00000001c88c7334 _UIGestureRecognizerSendActions + 264
	23  UIKitCore                           0x00000001c8fc2eec -[UIGestureRecognizer _updateGestureForActiveEvents] + 516
	24  UIKitCore                           0x00000001c86defdc _UIGestureEnvironmentUpdate + 2448
	25  UIKitCore                           0x00000001c88c23f0 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 296
	26  UIKitCore                           0x00000001c88c1f00 -[UIGestureEnvironment _updateForEvent:window:] + 188
	27  UIKitCore                           0x00000001c88c1cf0 -[UIWindow sendEvent:] + 3448
	28  UIKitCore                           0x00000001c88c07ec -[UIApplication sendEvent:] + 564
	29  UIKitCore                           0x00000001c88be9bc __dispatchPreprocessedEventFromEventQueue + 6448
	30  UIKitCore                           0x00000001c9459a18 __processEventQueue + 5508
	31  UIKitCore                           0x00000001c9453dc4 __eventFetcherSourceCallback + 152
	32  CoreFoundation                      0x00000001992194d8 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
	33  CoreFoundation                      0x000000019921946c __CFRunLoopDoSource0 + 176
	34  CoreFoundation                      0x00000001992191dc __CFRunLoopDoSources0 + 244
	35  CoreFoundation                      0x0000000199217dc8 __CFRunLoopRun + 828
	36  CoreFoundation                      0x0000000199217434 CFRunLoopRunSpecific + 608
	37  HIToolbox                           0x00000001a39c119c RunCurrentEventLoopInMode + 292
	38  HIToolbox                           0x00000001a39c0e2c ReceiveNextEventCommon + 220
	39  HIToolbox                           0x00000001a39c0d30 _BlockUntilNextEventMatchingListInModeWithFilter + 76
	40  AppKit                              0x000000019ca76cc8 _DPSNextEvent + 660
	41  AppKit                              0x000000019d26d4d0 -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 700
	42  AppKit                              0x000000019ca69ffc -[NSApplication run] + 476
	43  AppKit                              0x000000019ca41240 NSApplicationMain + 880
	44  AppKit                              0x000000019cc94654 +[NSWindow _savedFrameFromString:] + 0
	45  UIKitMacHelper                      0x00000001b24f5f50 UINSApplicationMain + 972
	46  UIKitCore                           0x00000001c86cd7bc UIApplicationMain + 148
	47  UIKitCore                           0x00000001c89a8de0 __swift_destroy_boxed_opaque_existential_1Tm + 12004
	48  GeoPS2                              0x00000001005dd788 $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 120
	49  GeoPS2                              0x00000001005dd700 $s6GeoPS211AppDelegateC5$mainyyFZ + 44
	50  GeoPS2                              0x00000001005dd804 main + 28
	51  dyld                                0x0000000198daf154 start + 2476
)
In MKMapView, show (some) annotations only when zoomed in
 
 
Q