Ответ 1
Эти два уведомления относятся к динамическому контенту на представлениях и сообщают об этих изменениях в VoiceOver для пользователей экранных прошивок. Существует мало различий между этими двумя уведомлениями, за исключением их поведения по умолчанию, и глупый маленький "звуковой сигнал" для уведомлений ScreenChange.
В обоих случаях аргумент
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, arg);
Представляет строку для считывания или элемент на экране, на который VoiceOver переключит свой фокус. В случае резких изменений контекста важно отправить фокус на место, которое имеет смысл, или объявить, что такие изменения произошли. Любой подход приемлем с точки зрения доступности, хотя я предпочитаю подходы, которые предполагают наименьшее количество возможных изменений. В случае простых изменений компоновки почти всегда лучше всего объявить об изменении контекста и оставить фокус там, где он был. Хотя иногда элемент, вызвавший изменение контекста, скрыт, и тогда, очевидно, необходимо прямое озвучивание, чтобы выделить новый контент, потому что поведение по умолчанию в этом случае undefined или, возможно, детерминированное, но определяется каркасом, который знает абсолютно ничего о вашем приложении!
Различие между двумя событиями, учитывая, что они оба делают точно то же самое, находится в их поведении по умолчанию. Если вы подаете нуль в UIAccessibilityLayoutChangedNotification
, то как будто вы ничего не сделали. Если вы предоставите аргумент nil для UIAccessibilityScreenChangedNotification
, он отправит фокус в первый UIObject в иерархии вашего представления, который будет помечен как элемент accessibilityElement, после того, как все изменения иерархии представлений и чертежи будут завершены.
UIAccessibilityLayoutChangedNotification
Хороший пример использования для UIAccessibilityLayoutChangedNotification
предназначен для динамических форм. Вы хотите сообщить пользователям, что на основе решений, которые они приняли в форме, доступны новые параметры. Например, если в форме вы выбираете, что вы являетесь ветераном, дополнительные области формы могут появляться, чтобы обеспечить больше ввода, но эти области, возможно, были скрыты для других пользователей, которые не заботились о них. Таким образом, вы можете переключать фокус на эти элементы после взаимодействия с пользователем:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, firstNewFormElement);
Что бы переключить фокус на предоставленный элемент и объявить его accessibilityLabel.
Или просто скажите им, что есть новые элементы формы:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, @"Veterans form elements available");
Что бы оставить фокус там, где он есть, но VoiceOver объявит "Элементы формы ветеранов".
Примечание. Это особое поведение прослушивается на моем iPad (8.1.2).
Или, наконец, вы можете сделать это:
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
Что абсолютно ничего:). Серьезно, я даже не думаю, что бэкэнд a11y заботится. Эта конкретная строка кода представляет собой полный отход!
UIAccessibilityScreenChangedNotification
Хорошим примером использования для UIAccessibilityScreenChangedNotification
является настраиваемый режим просмотра с вкладками. Когда изменяется весь экран, за исключением области навигации, изменяется. Вы хотите, чтобы озвучивание знало, что по существу весь экран изменился, но НЕ сфокусировать первый элемент (первую вкладку), а сосредоточить первый элемент содержимого.
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstNonGlobalNavElement);
который будет воспроизводить звук звукового сигнала "boop beep", а затем переключить фокус только под вашу глобальную навигационную панель. Или вы можете сделать это:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, @"You're on a new tab");
Что будет ждать загрузки новой вкладки, воспроизведения звука "звуковой сигнал" , анонса "Вы на новой вкладке" в озвучке, затем смените фокус на первый элемент на экране, а затем объявите accessibilityLabel для этот элемент. (PHEW! Это много! Это раздражает пользователей экрана. Избегайте этого сценария, если это абсолютно необходимо).
И, наконец, вы, конечно, можете это сделать:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
Что эквивалентно:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, firstA11yElement);
Оба из них будут воспроизводить звук "звуковой сигнал" , сдвигают фокусировку VoiceOver на первый элемент на экране, а затем объявляют об этом.
Наконец
В комментарии кто-то упомянул о кешировании, и я иногда комментирую в своем ответе о вещах, которые могут или не могут волновать A11y Backend. Хотя, конечно, возможно, что есть какая-то бэкэнд-магия, я не верю ни в одно из этих обстоятельств, задняя часть вообще не волнует. Причина, по которой я говорю это, заключается в следующем:
Если вы когда-либо использовали протокол UIAccessibilityContainer
, вы можете наблюдать, как запрашивается ваш контейнер просмотров. Кэширования не происходит. Даже свойство accessibilityElementCount
получает pinged каждый раз, когда VoiceOver меняет фокус на новый AccessibilityElement в вашем контейнере. Затем он проходит процесс проверки, на каком элементе он находится, запрашивает следующий элемент и т.д. Он сконструирован в своей основе для обработки динамических ситуаций. Если бы вы вставляли новый элемент в свой контейнер после взаимодействия, он все равно просматривал все эти запросы и был бы в порядке! Кроме того, если вы переопределите свойства протокола UIAccessibility, чтобы предоставить динамические подсказки и метки, вы также можете увидеть, что эти функции вызываются каждый раз! Как таковой, я считаю, что бэкэнд A11y Framework отображает информацию ABSOLUTELY ZERO из этих уведомлений. Единственная информация, которую VoiceOver должна выполнять, заключается в том, что в данный момент она сосредоточена на элементе доступности, а также на элементах Accessibility Container. Уведомления просто предназначены для того, чтобы ваше приложение стало более удобным для пользователей VoiceOver.
Представьте, если бы это было не так, сколько раз Safari отправлял эти уведомления!!!!:)
Эти конкретные утверждения могут быть подтверждены только кем-то с бэкэнд-знанием структуры, которая работает с кодом, и должна рассматриваться как гипотеза. Это может быть так, что это сильно зависит от версии/реализации. Определенно открыт для обсуждения этих вопросов! Остальная часть этого сообщения довольно конкретна.
Для справки
Большая часть этого исходит из опыта работы с фреймворками, но вот полезная ссылка, если вы хотите копать дальше.
https://developer.apple.com/documentation/uikit/accessibility/uiaccessibility
https://developer.apple.com/documentation/uikit/uiaccessibilitylayoutchangednotification
https://developer.apple.com/documentation/uikit/uiaccessibilityscreenchangednotification
И, наконец, репо с открытым исходным кодом из глупого маленького приложения, которое я собрал, чтобы проверить все это.