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
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