'VoiceOver reads table header twice and always adds the word "heading"

Here is my code:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return self.setupFriendsHeaderView()
}

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    view.accessibilityTraits = .none
    for subView in view.subviews {
        subView.accessibilityTraits = .none
    }
}

func setupFriendsHeaderView() -> UIView? {
    let view = UIView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: tableView.frame.width, height: 44)))

    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.switchPendingRequestsStatus)))
    view.isAccessibilityElement = true
    view.accessibilityLabel = "Pending requests"

    return view
}

When you tap the header first time VoiceOver says: "Pending requests. Pending requests header." Sometimes it doesn't manage to finish the first sentence and starts speaking the next one. The second time it just says "Pending requests header." What I need it to do is say "Pending requests" once, and no word "heading". I saw the answer recommending to use willDisplayHeaderView method, but it doesn't help at all.



Solution 1:[1]

The reason behind of announcing "Heading" is that UITableView adds header trait to the header views. To avoid this just simply subclass from UITableViewHeaderFooterView and override accessibilityTraits with empty traits like this:

override var accessibilityTraits: UIAccessibilityTraits {
  get { [] }
  set { }
}

Solution 2:[2]

I had this problem with a custom UITableViewHeaderFooterView with a custom UILabel. I found that setting the accessibilityLabel of the headerfooterview to the text of this custom label fixed the problem.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ard
Solution 2 bitwit