Is UIBarButtonItem no longer supporting accessibilityLabel in iOS 14?

Viewed 576

Update: This bug has been fixed in iOS 14.5


I have the following class embedded in a UINavigationController:

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let barButton = UIBarButtonItem(title: "Save", style: .plain, target: nil, action: nil)
        barButton.accessibilityLabel = "Save meeting"
        navigationItem.rightBarButtonItem = barButton
    }
}

When running iOS 14.4, the accessibility label is ignored and only the visible title is announced by VoiceOver. However, on iOS 13.7, the accessibility label is correctly used. Has the UIBarButtonItem usage changed or is this an iOS bug?

Screenshot for context:

Partial screenshot of iOS test application, showing OS status bar and, below it, navigation bar with Save button on right hand side
2 Answers

When I must implement a UIBarButtonItem, I always follow these instructions to be sure that a11y will be stable and completely functional.

I don't know if this situation is a bug or a kind of regression due to the new iOS version but implementing a11y in the navigation bar buttons as customization is a perfect way to encounter no unfortunate surprises even if it looks like a boilerplate solution.

I've created a blank project with a simple view controller embedded in a navigation controller where a right bar button is displayed as follows:

class NavBarViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        var a11yRightBarButton: UIBarButtonItem?
    
        let a11y = UILabel()
        a11y.text = "OK"
        a11y.sizeToFit()
        a11y.isUserInteractionEnabled = true //Mandatory to use the 'tap gesture'.
    
        a11yRightBarButton = UIBarButtonItem(customView: a11y)
    
        let tap = UITapGestureRecognizer(target: self,
                                         action: #selector(validateActions(info:)))
        a11yRightBarButton?.customView?.addGestureRecognizer(tap)
    
        a11yRightBarButton?.isAccessibilityElement = true
        a11yRightBarButton?.accessibilityTraits = .button
        a11yRightBarButton?.accessibilityLabel = "validate your actions"
    
        navigationItem.rightBarButtonItem = a11yRightBarButton
    }

    @objc func validateActions(info: Bool) -> Bool {
        print("hello")
        return true
    }
}

Your right bar button displays "OK" and VoiceOver reads out "validate your actions" under iOS 14.4 and Xcode 12.4.

Following this rationale, you can use a UIBarButtonItem as supporting the accessibilityLabel property in iOS 14.

Set accessibility of UIBarButtonItem to true.

    let barButton = UIBarButtonItem(title: "Save", style: .plain, target: nil, action: nil)
    barButton.accessibilityLabel = "Save meeting"
    barButton.isAccessibilityElement = true
    navigationItem.rightBarButtonItem = barButton
Related