UISegmentedControl segments and VoiceOver

I'm using a UISegmentedControl to ask the user to select from a range of numbers. The start of the range is not necessarily at 1.

When using VoiceOver, the segment that is focused reads the accessibilityLabel, followed by the accessibilityTrait ("button"), followed by the numeric position in the control ("x of y"), followed by the accessibilityHint.

How can I change the "x of y" that's spoken between the trait and the hint?

It's confusing when the user has just selected a segment labeled "10" and hears "ten. button. 11 of 11."
The short answer is you can't really do this. With a UISegmentedControl, you don't have access to the underlying segments themselves so you're limited in what accessibility API you can use here. Properties you set on the underlying images or labels you set will get propagated to those internal views, but you can't create custom classes of them

However, it's likely that the segmented control is doing the right thing here. If the number 10 is indeed the 11th segment (say your first segment is 0), it is indeed expected and correct that VoiceOver reads "10, 11 of 11." This tells the user that they've selected the element with label 10, which is the 11th item in the list. Similarly if they had selected 0 and it read 1 of 11, that would indicate to the user that they are on the first of 11 selections. You didn't provide a lot of details about what you're doing, but it is likely that you don't actually want the index information to match the accessibilityLabel in this case.

If you had a custom control where you implemented the underlying views/segments as a custom class, you could use accessibilityRowRange to customize this. https://developer.apple.com/documentation/uikit/uiaccessibilitycontainerdatatablecell/2865803-accessibilityrowrange

The range should have a length of the number of total items, and a location of the index of the current item. For example, if you had five segments, the second segment would have a range of (1, 5), since it is the second item (0 indexed), and there are 5 total items. However, for reasons I mentioned above, I'd really recommend just leaving things as is.

The canonical use case for this control in our application is an NPS score, which goes from 0 to 10.

We've added an accessibility hint that says "Where 0 is not at all likely and 10 is extremely likely". So the user is given context (assuming they haven't disabled accessibility hints).

In the medium term we plan to make this a custom control, so thank you for the tip about accessibilityRowRange!
I would say that even in this case, you would want the default behavior. Saying that something is 0 of 10 is inconsistent with the rest of the system. 0, 1 of 11 will make sense to VoiceOver users, it’s terminology they will be familiar with.

Note that in most cases on iOS we do not speak the rowRnagw at all, Segmented controls and tab bars are 2 places that we speak this, so thinking about it some more, even if you make a custom control we probably won’t speak the row range at all. Again though, I think you are fine in either case. If you stick with a segmented control the behavior you described seems accurate. And if you make a custom control, this string won’t be spoken at all, which also seems reasonable given these are numbered as they are, and you have a hint describing their purpose.
UISegmentedControl segments and VoiceOver
 
 
Q