Причина, по которой вы читаете заголовок во второй раз, кроется в вашем коде.
В вашем viewDidLoad
вы устанавливаете метку доступности стека, которую VoiceOver автоматически считывает, чтобы сообщить пользователю об изменении.
Далее вы сообщаете об этом изменении сообщением в вашем viewDidAppear
, которое VoiceOver естественным образом считывает.
Чтобы избежать этого, просто удалите stackView.accessibilityLabel = label.text
в вашем setupNavigationItem
добавьте этот фрагмент в вашу личную ленивую переменную метки init:
if (self.view.subviews.contains(stackView)) {
stackView.accessibilityLabel = label.text
}
Обновление stackView.accessibilityLabel
таким образом не вызывает VoiceOver, чтобы сообщить пользователю, и позволяет понять вашу цель.
Однако я не рекомендую зачитывать заголовок в качестве первого элемента новой страницы, если вы не измените порядок представленных элементов.
Пользователи VoiceOver, естественно, не догадаются, что другойЭлемент присутствует перед заголовком:
- Возможно, они не найдут способ вернуться на предыдущую страницу.
- Они могут быть потеряны, если получат первый элементстраницы с 4 пальцами просто нажмите , потому что они получат кнопку назад, а не заголовок.
Технически, Ваша проблема решена с кускомкода выше , но концептуально я предлагаю переупорядочить ваши элементы, если вы все еще хотите представить заголовок в качестве первого элемента.
==========
РЕДАКТИРОВАТЬ (обходной путь)
Что касается технической проблемы, вы правы в своем комментарии, это решение выше работает благодаря чтению метки VoiceOver.
Я зафиксировалрешение в вашей ветке git, которое вы дали в своем первоначальном посте.
Проблема связана с UIStackView, который я не могу объяснить в этом случае и не могу решить ни как есть.
Чтобы достичь вашей цели, ясоздал UIAccessibilityELement
для стека, который может быть идеально доступен и доступен без двойного чтения с пост-уведомлением.
Я сделал это, потому что не мог программно получить новый размер стека, когда надписи находятся в ...может быть кресть подкласс UIStackView и войти в его layoutSubviews
может быть хитростью?
Это решение должно работать как обходной путь , но я не знаю причину, почему это поведение появляется с UIStackview.
==========
РЕДАКТИРОВАТЬ (решение)
Проблема заключается в способе titleView
navigationItem
создано.Лучший способ достичь своей цели - это:
- Инициализировать ваш titleView как простой
UIView
, кадр которого совпадает с представлением стека. - Добавить представление стека как подпредставление послеуказав его фрейм и его свойства доступности.
Выполните следующие шаги в вашем коде:
Добавьте черту .header
в свойстве stackview:
private lazy var stackView: UIStackView = {
let stackView = UIStackView(frame: .zero)
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .equalSpacing
stackView.isAccessibilityElement = true
stackView.accessibilityTraits = .header
return stackView
}()
Измените регистр стека в разделе кода "switch ... case ...", как показано ниже:
case .stackView:
label.text = "UIStackView"
label.sizeToFit()
stackView.addArrangedSubview(label)
label2.text = subtitle
label2.sizeToFit()
stackView.addArrangedSubview(label2)
stackView.frame.size.width = max(label.frame.width, label2.frame.width)
stackView.frame.size.height = label.frame.height + label2.frame.height
stackView.accessibilityLabel = label.text?.appending(", \(label2.text!)")
navigationItem.titleView = UIView(frame: stackView.frame)
navigationItem.titleView?.addSubview(stackView)
}
Теперь postNotification
считывает ваш стек только один раз как первый элемент вашего экрана.