BottomBar BarButtonItem Voice Over доступность нарушена

Я заметил, что есть некоторые проблемы со стандартным поведением Voice Over с BarButtonItems, когда они размещены в нижней панели View.

В тестовом приложении я сделал следующее простое представление

Тестовое приложение, отображающее элементы верхней панели, кнопки нижней панели и метку

С помощью следующего кода я обновляю все 3 текстовых элемента, чтобы они подсчитывали каждую секунду.

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *testLabel;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *testBarButtonItem;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *testBottomBarItem;

@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic) NSInteger count;

@end

@implementation ViewController

- (void)viewDidLoad
{
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.

  self.count = 0;
  self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];

  // run the timer for the common modes so it's not interrupted with scrolling - should be ticked in pretty much all modes now
  [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

  self.testLabel.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently;
  self.testBarButtonItem.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently;
  self.testBottomBarItem.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently;
}

-(void)updateTimer:(NSTimer*)theTimer
{
  self.testLabel.text = [NSString stringWithFormat:@"Label with value %d", (int)self.count];
  self.testBarButtonItem.title = [NSString stringWithFormat:@"Top Item with title %d", (int)self.count];
  self.testBottomBarItem.title = [NSString stringWithFormat:@"Bottom Item with title %d", (int)self.count];
  self.count++;
}

При тестировании этого приложения на моем iPhone 6+ с включенным Voice Over происходит следующее

  • Элемент кнопки верхней панели пульсирует по мере обновления содержимого
  • Элемент кнопки верхней панели правильно считывает обновленное содержимое из-за установленной черты UIAccessibilityTraitUpdatesFrequently
  • Метка в центре правильно считывает обновленное содержимое из-за установленной черты UIAccessibilityTraitUpdatesFrequently
  • Элемент кнопки "Нижняя панель" НЕ считывает обновленное содержимое правильно, даже если для него также установлена ​​черта UIAccessibilityTraitUpdatesFrequently
  • при навигации по элементам специальных возможностей с пролистыванием влево / вправо, начиная с элемента кнопки верхней панели, выделение корректно перемещается вниз до метки с пролистыванием вправо, но оттуда пролистывание вправо переносит выделение в верхний левый угол представления (где отсутствует элемент управления). Затем он считывает исходное содержимое кнопки нижней панели "Нижний элемент с заголовком 0" независимо от того, что фактически читает нижняя кнопка. Только при активном выборе элемента нижней панели он действительно правильно выбирает и считывает его. Но, как уже описано, он не продолжает читать его

Я считаю, что навигационная ошибка, возможно, является новой в iOS 8.4, поскольку я не заметил в своем основном приложении того, что я проводил голосовое тестирование в течение длительного времени, но я мог просто пропустить его.

У меня не было большого успеха с использованием UIAccessibilityTraitUpdatesFrequently в моем собственном приложении, но я вижу другие приложения, которые, по-видимому, работают с ним правильно. Так что если кто-то может указать на то, что я делаю неправильно, это было бы здорово. В противном случае я думаю, что я буду регистрировать ошибку радара по этому поводу.

Для справки я сейчас выложил весь проект в виде почтового индекса для скачивания здесь

Здесь есть видео этой ошибки в действии

https://youtu.be/QokQ0MDGyZM

1 ответ

Вы, кажется, неправильно поняли, что UIAccessibilityTraitUpdatesFrequently делает. Он не предназначен для того, чтобы гарантировать, что ваш контент считывается, так как он динамически меняется. Это необходимо для того, чтобы чрезмерно подробный контент, такой как таймер, не считывал каждое обновление. Например, если вы хотите сфокусироваться на таймере, который обновляется каждую секунду. VoiceOver будет читать

1 2 3 4 ...

Впрочем, допустим, что это время. Итак, он должен зачитать:

1 час 20 минут 55 секунд 1 час 20 минут 56 секунд...

НО, к тому времени, как он прочитал все первое объявление "... 55 секунд", таймер теперь фактически показывает 1:21:00. Тем не менее, он по-прежнему считывает "... 56 секунд" и затем продолжает читать "… 57 секунд", в то время как таймер и фактическое объявление становятся все более и более несинхронными.

Нет ничего, что автоматически считывало бы содержимое автообновления, если VoiceOver не фокусирует его. Это может привести к хаосу и множеству проблем с доступностью. Разработчик должен уведомить VoiceOver о динамических изменениях путем соответствующей публикации следующих трех уведомлений о специальных возможностях:

UIAccessibilityLayoutChangedNotification
UIAccessibilityScreenChangedNotification
UIAccessibilityAnnouncementNotification

Обратите внимание, что их поведение немного нестабильно в типичной среде тестирования. В частности, я обнаружил, что вы хотите убедиться, что VoiceOver включен, ДО того, как вы откроете свое приложение. Использование быстрого переключения, когда ваше приложение запущено, является хорошим способом устранения ошибок VoiceOver, когда дело доходит до системы уведомлений. Еще лучше включить VoiceOver, перезагрузить телефон и оставить его включенным во время тестирования.

Другие вопросы по тегам