Search code examples
iosaccessibilitymapkitmkmapviewvoiceover

MKAnnotationView custom callout is invisible to Accessibility (VoiceOver)


I have a MKAnnotationView subclass and place several of them on an MKMapView. The MKAnnotationView subclass sets some accessibility elements like this:

func applyAccessibility() {
    
    self.isAccessibilityElement = true
    self.accessibilityTraits = [.none]
    
    self.accessibilityLabel = "Bus stop map pin"
    self.accessibilityValue = busStop.name
}

VoiceOver reads out the names of the bus stops that are pinned on the map.

I then use a UIView subclass as the callout view when a bus stop is tapped.

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    
    if let annotation = view.annotation
    {
        if annotation is MKUserLocation
        {
            // This is our location marker
            return
        }
        
        busStopAnnotationCalloutView.setupForAnnotationView(view, delegate: self)
        
        view.addSubview(busStopAnnotationCalloutView)
        
        mapView.setCenter(annotation.coordinate, animated: true)
    }
}

This works great, however this callout view is totally invisible to VoiceOver.

In the init of the callout view I set:

isAccessibilityElement = true
accessibilityTraits = .none
accessibilityLabel = "Callout view"
accessibilityIdentifier = "BusStopAnnotationCalloutView.callout"

and it also creates it's own labels and a button of which I set similar like this:

label.isAccessibilityElement = true
label.accessibilityTraits = .header
label.accessibilityLabel = "\(busStop.name)"

UIButton

button.isAccessibilityElement = true
button.accessibilityTraits = .button
button.accessibilityLabel = "Select this bus stop"

but none of these elements are visible to VoiceOver. The Accessibility Inspector can't see them.

As I move around the view with the Accessibility Inspector it just picks up and MKAnnotation's that are on the map underneath the callout.

EDIT --------

I have created a small example project that has a custom callout view that just won't get any accessibility.

Example project

And there's also a short screen recording showing the problem:

Video thumbnail
on YouTube


Solution

  • The issue here is that your callout view is a child of your annotation view. Therefore if your annotation view has it's isAccessibilityElement set to true you can not focus on the callout. A way of solving this is setting the isAccessibilityElement of your annotation to false each time it is selected and vice versa.