I’m encountering what appears to be a synchronization issue between the numbers displayed by the iOS Voice Control overlay and the targets Voice Control actually activates. Environment:
- iPhone 13 Pro Max
- iOS 26.6.1
- React Native 0.86.3
- Expo SDK 57.0.17
- Fabric/New Architecture enabled
The issue occurs on a tutorial screen containing several interactive elements. After the screen changes or elements become enabled, disabled, mounted, or unmounted, Voice Control displays numbered overlays that do not correspond to its current command mapping. For example:
- Enable Voice Control and say “Show numbers.”
- Navigate to the affected tutorial step.
- The visible overlay places number 5 on an interactive square.
- Say “Tap 5.”
- Instead of activating that square, Voice Control activates the “Skip Tutorial” button.
If I say “Hide numbers” followed by “Show numbers,” the newly displayed numbers reflect the actual command mapping. This demonstrates that:
- Voice Control’s internal target mapping has updated correctly.
- The visible number overlay has retained an older mapping.
- Saying a displayed number can therefore activate a completely different control.
The behavior is reproducible in an older build that predates our Voice Control-specific tutorial changes, so it does not appear to have been caused by those changes. Setting the Voice Control overlay to “None” also does not resolve the underlying synchronization issue. I found a nearly identical cross-framework report in Flutter: https://github.com/flutter/flutter/issues/183821 That report describes the number overlay showing one mapping after button enabled-state changes while “Tap N” uses a different mapping. It remains open and does not appear to have a published workaround. Questions:
- Is this a known iOS Voice Control issue?
- Is there a supported way for an app to notify Voice Control that it must recalculate and redraw its numbered overlay?
- Would posting a UIAccessibility layout- or screen-changed notification help, or does Voice Control maintain this overlay independently?
- Are there particular patterns involving enabled/disabled or dynamically mounted accessibility elements that applications should avoid?
- Is there any way for an application to inspect the target associated with a Voice Control overlay number? My understanding is that these numbers are not exposed through a public API.
This issue is especially concerning because the visible overlay instructs the user to say a number that can activate an unrelated control. In this example, it can activate “Skip Tutorial.” I can provide screen recordings and a minimal reproduction if helpful.
The fact that the workaround “hide numbers” / “show numbers” corrects the behavior strongly indicates that Voice Control is operating on a stale Accessibility tree.
The starting position in making a good Voice Control experience is always “Be a good VoiceOver citizen.” Both Accessibility technologies use the same underlying infrastructure.
The answers to your specific questions are:
- Known issue? Not as such.
- Notify VC to recalculate? Yes. Specifically…
- Post a layout changed notification? Yes. Many events automatically trigger VC to refresh, but you can explicitly trigger a refresh the same way you would notify VoiceOver of a content change.
- Patterns to avoid? None come to mind.
- A way to inspect? Not really from within your app’s process. Your app tells the Accessibility technologies what is interactable, and it’s the system’s responsibility to respect that. You might try using Accessibility Inspector to visualize what Voice Control/VoiceOver are seeing, or use the Voice Control “show names” overlay to get more insight into what a given Voice Control label is associated with.
Hope this helps.