Why is UIAccessibility.post(notification: .announcement, argument: “arg”) not announced in voice over?

前端 未结 4 2265
温柔的废话
温柔的废话 2021-02-14 20:34

When using Voice Over in iOS, calling UIAccessibility.post(notification:argument:) to announce a field error doesn\'t actually announce the error.

I have a

4条回答
  •  闹比i
    闹比i (楼主)
    2021-02-14 20:50

    I am able to get this to work using a retry mechanism where I register as an observer of the UIAccessibility.announcementDidFinishNotification and then pull the announcement and success status out of the userInfo dictionary.

    If the success status is false and the announcement is the same as the one I just sent, I post the notification again. This happens on repeat until the announcement was successful.

    There are obviously multiple problems with this approach including having to de-register, what happens if another object manages to post the same announcement (this shouldn't ever happen in practice but in theory it could), having to keep track of the last announcement sent, etc.

    The code would look like:

    private var _errors: [String] = []
    private var _lastAnnouncement: String = ""
    
    init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(announcementFinished(_:)),
            name: UIAccessibility.announcementDidFinishNotification,
            object: nil
        )
    }
    
    func showErrors() {
        if !_errors.isEmpty {
            view.errorLabel.text = _errors.first!
            view.errorLabel.isHidden = false
    
            if UIAccessibility.isVoiceOverRunning {
                _lastAnnouncement = _errors.first!
                UIAccessibility.post(notification: .announcement, argument: _errors.first!)
            }
        } else {
            view.errorLabel.text = ""
            view.errorLabel.isHidden = true
        }
    }
    
    @objc func announcementFinished(_ sender: Notification) {
        guard let announcement = sender.userInfo![UIAccessibility.announcementStringValueUserInfoKey] as? String else { return }
        guard let success = sender.userInfo![UIAccessibility.announcementWasSuccessfulUserInfoKey] as? Bool else { return }
    
        if !success && announcement == _lastAnnouncement {
            _lastAnnouncement = _errors.first!
            UIAccessibility.post(notification: .announcement, argument: _errors.first!)
        }
    }
    

    The problem is that this retry mechanism will always be used because the first call to UIAccessibility.post(notification: .announcement, argument: _errors.first!) always (unless I am stopped on a breakpoint). I still don't know why the first post always fails.

提交回复
热议问题