Alex M
Alex M

Reputation: 185

iOS - Unexpected VoiceOver behavior on customized UIPickerView

I have a somewhat customized UIPickerView in my app. Basically I use pickerView:viewForRow:forComponent:reusingView returning a simple UILabel. As I started working on making the app more accessible, I noticed that VoiceOver reads label and adds, say, "3 of 300" (i.e. row number "of" total rows). This is not a desired behavior.

While trying to troubleshoot this, I found that if I use pickerView:titleForRow:forComponent instead of pickerView:viewForRow:forComponent:reusingView, without any other changes, then I get the desired behavior of VoiceOver simply reading the "title" of the selected row. I tested this on iOS 9.

Question is: how do I get UIPickerView back to the "normal" VoiceOver behavior, while still using pickerView:viewForRow:forComponent:reusingView? Thanks for any help!

Upvotes: 4

Views: 1582

Answers (2)

Robert
Robert

Reputation: 38213

One fix will be to check if voice over is running

UIAccessibilityIsVoiceOverRunning()

If so use titleForRow otherwise use viewForRow. That way you don't degrade normal experience.

Upvotes: 0

Alex M
Alex M

Reputation: 185

I asked Apple support for help on this. The official reply was: "Our engineers have reviewed your request and have concluded that there is no supported way to achieve the desired functionality given the currently shipping system configurations". (For posterity - this was when the newest iOS version was 9.4). They suggested to file a request for new functionality, which I may do.

To solve this problem I went with the following workaround.

  • Created a base class almost identical to the class I had, but implementing only pickerView:titleForRow:forComponent and not pickerView:viewForRow:forComponent:reusingView. This class presents vanilla non-customized picker.
  • Created a subclass of that base class, now implementing pickerView:viewForRow:forComponent:reusingView. This class presents a fully customized picker.
  • In my code elsewhere used UIAccessibilityIsVoiceOverRunning() to create an object of base class when VoiceOver is on, and an object of the subclass otherwise

Thus when a user is running VoiceOver, they get a visually ugly picker, but one that is perfectly well-behaved in terms of accessibility (i.e. no row number announcements). Which is a perfectly reasonable "compromise" I think, since the user is basically guaranteed not to care about the visual appearances.

Upvotes: 5

Related Questions