Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make UIAlertController accessibilityLabel different from title

I'm hinting some strings in my app for VoiceOver. I'm expanding some abbreviations, like "opp" → "opposite" and "ave" → "avenue", so that VoiceOver pronounces them correctly. However, I want to use one of these strings as the title of a UIAlertController (iOS 9+). I want to set the title to the unmodified string, but the accessibilityLabel to the pronounceable string. Is this possible without traversing the subviews, which is fragile so I'd rather avoid it?

like image 239
Zev Eisenberg Avatar asked Oct 26 '25 09:10

Zev Eisenberg


2 Answers

It appears that this is not possible. I've filed a radar.

like image 127
Zev Eisenberg Avatar answered Oct 28 '25 23:10

Zev Eisenberg


Although this approach doesn't satisfy the OP's desire to avoid traversing the subviews it may be useful to someone:

import UIKit

class ViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        let titleText = NSLocalizedString("File eBill", comment: "File eBill Header Title")
        let userMessage = NSLocalizedString("The eBill could not be filed.", comment: "File eBill Error")
        let alert = UIAlertController(title: titleText, message: userMessage, preferredStyle: UIAlertController.Style.alert )

        if let titleLabel = alert.view.firstLabel(with: titleText) {
            let pronunciationTitle = NSLocalizedString("File e-Bill", comment: "File eBill pronunciation")
            titleLabel.accessibilityLabel = pronunciationTitle
        }
        if let messageLabel = alert.view.firstLabel(with: userMessage) {
            let pronunciationMessage = NSLocalizedString("The e-Bill could not be filed.", comment: "File eBill error pronunciation")
            messageLabel.accessibilityLabel = pronunciationMessage
        }

        alert.addAction(UIAlertAction(title: "Done", style: UIAlertAction.Style.default, handler: { (action) -> Void in
            print("Done")
        }))
        self.present(alert, animated: true, completion: nil)
    }

}

extension UIView {

    /// Returns a UILabel that matches the text input if such exists within the view.
    /// Probes recursively and exhaustively.
    func firstLabel(with text: String) -> UILabel? {
        var result: UILabel?
        for view in subviews {
            if let label: UILabel = view as? UILabel,
               label.text == text {
                result = label
                break
            } else {
                if let deeper = view.firstLabel(with: text) {
                    result = deeper
                    break
                }
            }
        }
        return result
    }
}
like image 33
Matt Bearson Avatar answered Oct 29 '25 00:10

Matt Bearson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!