0

I've noticed that there are some issues with standard Voice Over behaviour with BarButtonItems when they are placed in the bottom bar of a View.

In a test app I've made the following simple view

Test App Showing Top Bar, Bottom Bar button items and a label

With the following code I'm updating all 3 text elements so they count up every second.

@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++;
}

Testing this app on my iPhone 6+ with Voice Over enabled, the following occurs

  • The Top Bar Button Item pulses as it updates its content
  • The Top Bar Button Item reads out its updated content correctly due to the UIAccessibilityTraitUpdatesFrequently trait being set
  • The Label in the centre reads out its updated content correctly due to the UIAccessibilityTraitUpdatesFrequently trait being set
  • The Bottom Bar Button Item does NOT read out its updated content correctly, even though it too has the UIAccessibilityTraitUpdatesFrequently trait set
  • when navigating Accessibility elements with left/right swipes starting from the top bar button item, selection correctly moves down to the label with a right swipe, but from there a right swipe takes the selection to the top left of the view (where no control resides). It then reads out the initial bottom bar button content "Bottom Item With title 0" regardless of what the bottom button actually reads. Only when actively selecting the bottom bar item does it actually correctly select it and read it out. But as already described it does not go on to continue reading it out

The navigation bug I believe is maybe new in iOS 8.4 as I've not noticed it in my main app that I've been doing voice over testing for a long time, but I could have just missed it.

I've not had much success with using UIAccessibilityTraitUpdatesFrequently in my own app, yet I see other apps out there that seemingly are working with it correctly. So if anyone can point out something that I'm doing wrong that'd be great. Otherwise I think I'll log a radar bug about this.

For reference I've now put up the entire project as a zip for download here

There's a video of this bug in action here

https://youtu.be/QokQ0MDGyZM

jimbobuk
  • 1,211
  • 12
  • 25

1 Answers1

2

You seem to misunderstand what the UIAccessibilityTraitUpdatesFrequently does. It is not there to ensure your content is read out as it changes dynamically. It is there to ensure that overly verbose content, like a timer, does not read out every update. For example, if you were to put focus onto a timer that updated every second. VoiceOver would read out

1 2 3 4 ...

However, let's say that this is a time. So it has to read out:

1 hour, 20 minutes, 55 seconds 1 hour, 20 minutes, 56 seconds ...

BUT, by the time it has read the entire first announcement "... 55 seconds" the timer now actually reads 1:21:00. Yet it still reads out "... 56 seconds" and would then continue to read out "... 57 seconds" meanwhile, the timer and the actual announcement are getting farther and farther out of sync.

There is nothing that will automatically read out auto updating content, if VoiceOver is not focusing it. This would cause havoc, and a lot of accessibility issues. It is on the developer to notify VoiceOver of dynamic changes by appropriately posting the following three accessibility notifications:

UIAccessibilityLayoutChangedNotification
UIAccessibilityScreenChangedNotification
UIAccessibilityAnnouncementNotification

Note that the behavior of these is a little unstable in your typical testing environment. In particular I've found that, you want to ensure that you have VoiceOver on BEFORE you open your app. Using the quick toggle shortcut while your app is up is a good way to bug VoiceOver out when it comes to the notification system. Even better is to turn VoiceOver on, restart your phone, and leave it on while you test.

MobA11y
  • 18,425
  • 3
  • 49
  • 76
  • Thanks for the detailed reply ChrisCM. Just wanted to say if it wasn't clear that I'm talking about it reading out content correctly when the particular item is selected. The labels read out continuously as their contents updates with a small gap as you described as the content updates more frequently than the announcement. – jimbobuk Jul 04 '15 at 17:56
  • The bottom bar button item however does NOT read out its content more than once. It also doesn't show its selection properly as described. Nor does it ever return YES in its Accessibilty is focussed method. I'm going to log bugs about it, could put the project online for you and anyone else to reference and test yourselves? – jimbobuk Jul 04 '15 at 18:04
  • I don't expect content to read out that isn't selected, but I do expect consistency with focussed content being read out across the board. I've posted another question on here about tableviews misbehaving and have another about view titles not being consistent either. Basically I'm getting all my issues from my app together in test apps to ask on here and/or log as bugs. – jimbobuk Jul 04 '15 at 18:10
  • Good to know about changing voice over on the fly, it's on my todo list to make my app handle it as some views behave a little different in voiceover to normal and I will want them to eventually dynamically update as the mode changes if possible. – jimbobuk Jul 04 '15 at 18:10
  • You should post the repos. Not just code snippets. – MobA11y Jul 06 '15 at 13:13
  • will do. Wasn't sure if projects included anything to do with my own account details. I've made a dummy company name and what not but yeah I can try and upload the zips later... I've already created apple bugs for them, but maybe i'm doing something silly... though in this case the snippet is the majority of the actual relevant code. Still nice to run it and see for yourself. Would really love to find some folks like yourself to chat accessibility stuff as it seems to be a not that well trodden path at times! – jimbobuk Jul 06 '15 at 17:54
  • Just post them as a Gist or an open source repo on GitHub. I know it probably seems like the important code is there, but I've been doing iOS Accessibility for a long time, and more so than in other areas, the issues can be hiding in XML or in the way you set up the view hierarchy. So it's best just to make sure we have the same code. You should check out the app my company put together to help with A11y concepts on iOS. Deque University for iOS. It's Open Source, if you're interested, we could work together on incorporating a "Story" like this into the app. – MobA11y Jul 06 '15 at 18:24
  • Just downloaded your app, will take a look at it. I don't know whether this particular example would be worth adding or not. To me it speaks of a bug in the OS implementation. It would be good to hear someone else gets the same result locally running the app and see if you can see what's causing it. I've got about 5-6 separate bugs to make test apps for, mainly to hopefully let apple repro the issues and hopefully fix them. – jimbobuk Jul 06 '15 at 21:36
  • The source is available in the original question as a downloadable .zip file. See how you find it. Thanks for your time though ChrisCM, really appreciated! – jimbobuk Jul 06 '15 at 21:37
  • I've also updated this other question for tableviewcells not reading out updating content when focused with similar source in case you're interested :) - http://stackoverflow.com/questions/31195667/ios-uitableview-cells-dont-work-with-voice-over-uiaccessibilitytraitupdatesfreq – jimbobuk Jul 06 '15 at 21:42
  • Also this morning i recorded videos of the bug in action and added them to the original question. Just so you can see and hear what I'm describing. – jimbobuk Jul 07 '15 at 09:56