К сожалению, Voice Over имеет много ошибок (в начале своего существования он был намного лучше, но с изменениями в последующих iOS версиях он ухудшился). Заставить его вести себя по-другому - это много "взломать", и с новой системой он может снова вести себя так, как вы этого не сделаете. Сказав, что я представлю решение, которое можно использовать, по крайней мере, на данный момент.
При запуске я должен сказать, что приостановка VoiceOver не возможна программно, потому что это вызывает cra sh ( проверьте здесь ). И поэтому
UIAccessibility.post(notification: .pauseAssistiveTechnology, argument: UIAccessibility.AssistiveTechnologyIdentifier.notificationVoiceOver)
не поможет.
Лучший способ обработки UITableViewCell с помощью UISwitch - это сделать так же, как Apple, в настройках iPhone (фокусировка Voice Over on целая клетка). Таким образом, ваш переключатель не должен быть элементом доступности.
А теперь самое забавное, что нужно обнаружить - если флаг switch.isUserInteractionEnabled установлен в значение true, то двойное нажатие на ячейку не вызовет
tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath)
или
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
, поэтому система будет go по умолчанию и будет считывать новое значение ползунка сразу после его изменения.
Но если вы создадите метод для установки новой ячейки, снятой с очереди (( внутри вашего пользовательского класса ячеек) и напишите что-то вроде этого
func setup() {
slider.isUserInteractionEnabled = !UIAccessibility.isVoiceOverRunning //if VO is running you can't normally tap slider so it won't affect user experience
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self, selector: #selector(setSwitchAccessibility), name: UIAccessibility.voiceOverStatusDidChangeNotification, object: nil)
}
@objc func setSwitchAccessibility() {
slider.isUserInteractionEnabled = !UIAccessibility.isVoiceOverRunning //without VO user should be able to interact with switch directly or / and by selecting cell
}
, тогда будет вызван ваш делегат таблицы, позволяющий сделать что-то свое Наблюдение за передачей голоса необходимо для того, чтобы разрешить обработку переключения при отключении Voice Over.
Под «чем-то нестандартным» я понимаю отображение индикатора активности в willSelectRow и перемещение фокуса на
UIAccessibility.post(notification: .layoutChanged, argument: activityIndicatorView)
и настройку значение доступности, равное nil (установите его снова в значение доступности ползунка непосредственно перед восстановлением фокуса Voice Over на ячейке).
Также - после удаления значения доступности из ячейки Voice Over прочитает метку доступности этой ячейки, если она существует. В этом случае вам нужно временно перезаписать значение по умолчанию accessibilityLabel с помощью настраиваемого свойства этой ячейки (значение nil), чтобы сделать его беззвучным, используя что-то вроде этого:
var labelToReturn: String? = ""
override func accessibilityActivate() -> Bool {
self.accessibilityValue = nil
labelToReturn = nil
return false
}
override var accessibilityLabel: String? {
get {return labelToReturn == nil ? labelToReturn: super.accessibilityLabel}
set {super.accessibilityLabel = newValue}
}
Не забудьте изменить labelToReturn
на что-то другое перед удалением сфокусироваться на индикаторе вашей активности.