VoiceOver tips for iPhone developers

I've been working on improving VoiceOver support for Delivery Status touch 3.0. It was pretty simple for the most part, but there are a couple of things in particular that I struggled with. I couldn't find much information about this elsewhere, so I thought I'd share.

The first problem was adding accessibility labels to a UISegmentedControl. It should be automatic if you're using text labels for the segments, but if you're using images, there's no obvious way to do it. After a lot of trial and error, this is what I wound up with:

<pre>NSUInteger buttonCount = 0; for (UIView *thisView in pageControl.subviews) { switch (buttonCount) { case 0: thisView.accessibilityValue = NSLocalizedString(@"Previous Delivery",nil); break; case 1: thisView.accessibilityValue = NSLocalizedString(@"Next Delivery",nil); break; } buttonCount++; }</pre>

This particular control is a pair of up and down arrows—just like the ones you see in Mail, in the top-right corner, when you're viewing an email. The end result of this code isn't quite perfect. It's not particularly obvious when a button is disabled, and the text is read as "Next Delivery. Button. Image." I tried a few different tricks and couldn't get rid of the unnecessary "Image" statement. Mail has the exact same quirks, so we may have to wait for Apple to improve this. Also note that I'm setting the accessibilityValue, not the accessibilityLabel. Setting the latter didn't work.

The second problem I had was setting the accessibility label of a UIBarButtonItem, again with a button that only displays an image. I tried everything I could, and it was always read as simply "Button". The good news is, this was fixed in the iPhone OS 3.1 update. Just set the accessibilityLabel, and it will work as expected.


This entry has 2 comments.


Dawn wrote on September 30, 2009:

Thanks for pointing me to a workaround. You're right,here's still a lot missing from the accessilbity API. It seems like the following should indicate a disabled button but it doesn't work.

thisView.accessibilityTraits |= UIAccessibilityTraitNotEnabled;

One thing that could break your code is if the order changes in segmentedControl.subviews. Shouldn't these subviews contain a subview which is one of the segment images? Maybe for each subview you could check to see if it contains one of your button images and then apply the appropriate label.

It seems something like this should work.

for (UIView *thisView in segmentedControl.subviews) {
for (UIView *thisSubView in thisView.subviews) {
if ([thisSubView isEqual:[segctrl imageforsegmentatindex:0]]) {
thisView.accessibilityValue = NSLocalizedString(@"foo", nil);
} else if ([thisSubView isEqual:[segctrl imageforsegmentatindex:1]]) {
thisView.accessibilityValue = NSLocalizedString(@"bar", nil);


steve wrote on October 1, 2009:

thisView.accessibilityTraits |= UIAccessibilityTraitNotEnabled;

this looks like it would not work because you're trying to use it as a property

try this instead, i think it should work

[thisView setAccessibilityTraits: UIAccessibilityTraitNotEnabled | [thisview accessibilitytraits]]

Of course its also possible that traits cannot be set on segmented controls, which would just be a bug.

View more


My First WWDC Above: Apple's live App Store wall at WWDC. It showed icons of 20,000 iPhone apps,…

Displaying a password or text entry prompt on the iPhone Writing your own iPhone or iPod touch app, and wondering how to create an alert like…

Junecloud: coming soon

Tense Log 2.1 beta 2 now available! (Updated) Above: the Tense Log crop tool, a new feature in version 2.1 This is a pretty big…