VoiceOver kept throwing me to the Back button. It wasn't my code.

By Yahya , GABLVM Staff, 27 September 2026

I've been building the GABLVM iOS app for a while now, and for weeks I had this annoying thing happening. I'd be in the Learn tab, double tap Play on a dua or a phrase from a lesson, the recording would start fine, and about a second later VoiceOver would just dump me on the Back button. Not every time I touched the app. Just when I started a recording. I'd swipe back down, find my place, keep going. I honestly figured it was my phone doing something weird, so I didn't even write it down. Then testers started reporting the same thing, more than once, and I couldn't call it my phone anymore.

Then I got tired of it and decided to actually chase it. It took four builds and I was wrong three times, so if you're an accessibility person I think the wrong turns are the useful part.

The obvious answer

If you've done any VoiceOver work you already know the first thing I thought. The Play button changes when you tap it. Icon goes from play to pause, the value says Playing. If a focused element changes under VoiceOver, VoiceOver can lose it and land on the first thing on the screen. I've had that exact bug twice before in this app. Fixed it both times by keeping the label the same and putting the state in the value. Classic.

So I did that again. Made the buttons keep one name and one icon under VoiceOver. Shipped it to myself. Tapped Play. Back button.

Okay, maybe the value changing is enough. I made the buttons show no state at all under VoiceOver, which is how the Quran verse rows in the same app already work. Shipped it. Tapped Play. Back button.

Two builds, nothing. And looking back, both theories were dumb for the same reason. If the button redrawing was throwing focus, it would happen the instant I tapped. This was happening a full second later. I just hadn't paid attention to the timing because I was too busy being sure I knew the answer.

Ruling things out the cheap way

Before I changed anything else I ran a few tests that didn't need a build. Same card has a counter button that changes its text every tap. Held focus. There's a Play the whole chapter button at the top that isn't inside the list. Held focus, twice. Then on the next build it didn't, which told me the "twice" was luck. The Quran tab has Play this verse only, which creates a brand new audio player every single time, and that one held too. I was so sure about that one.

Each of those killed a theory. None of them told me what was actually going on.

So I made the app tell me

The app already keeps a diagnostic log you can share from Settings, About. What it didn't have was VoiceOver's side of things. iOS will actually tell an app every time VoiceOver focus moves, where it came from and where it went, and whether an announcement got to finish. So I added that. Only on the lesson and dua screens, only labels of controls, no values, nothing typed, because people share that log and I'm not logging someone's text field.

One log later I had the answer to the question I'd been guessing at. Clip started at 01:11:00.373. Focus still on the button. Focus gone at 01:11:02.021 and on the Back button five milliseconds after that. One point six five seconds after my tap. Right about when the stream would have actually started making sound. And on a pause or a resume, nothing. Only cold starts.

So the button was innocent. Something was happening when the audio started.

The phone's own log

The app couldn't see any further than that, so I went one level down. If you plug the iPhone into a Mac you can pull the system log for the minutes around a repro, and that log includes what iOS itself did, including VoiceOver, which shows up as a process called vot.

Here's what it showed. Audio starts. Fifty milliseconds later a system process called MediaRemoteUI, the thing that draws the Now Playing controls, puts a window on screen, grabs keyboard focus for six milliseconds, and takes it away again. VoiceOver sees a window appear and disappear, plays its screen change sound, and about a second later logs "First element in app focus" and picks the Back button. Which is exactly what VoiceOver is supposed to do after a screen change. It just shouldn't have counted as one.

Why only sometimes

That window shows up when an app opens a new Now Playing session. If there's already a session open, paused or playing, nothing shows. The Quran player only ever pauses, so it opens one session and keeps it forever, which is why it looked immune. It isn't. Force quit the app, play a surah, and it jumps. I've used this app every day for months and never put those two things together.

The Learn tab did it every time because of me. When a recording finished, my code cleared the Now Playing card completely. That closes the session. So every tap was opening a brand new one, and every new one flashed that window.

I tested that four ways. Quran's first play jumps, later plays don't. A dua started while a surah is sitting paused doesn't jump. A dua started right after another dua finished does. And that verse button I was so sure about, played as the very first sound after a fresh launch, jumps. That last one was the test that could've broken the whole theory, and it didn't. I don't think I've ever been happier to be wrong about my own app.

The fix

Small, once you know. A finished Learn recording now stays parked at its start with its card up, and the next recording reuses the session. Nothing closes, nothing flashes, VoiceOver stays where you left it. Play from the lock screen or Magic Tap plays the finished one again, which honestly is what I'd want anyway.

There's one case left and it belongs to iOS. The very first sound in an app session still has to open a session, so it can still move focus once. For that one case the app checks where VoiceOver is when the sound starts and puts focus back on the button you tapped, but only if it actually left. You hear the button name once. I'm sending Apple the logs, because a system window that exists for six milliseconds during Now Playing setup shouldn't be a screen change as far as VoiceOver is concerned.

The part I actually care about

Nothing visible happens when this fires, so my sighted testers had no way to catch it, and a scanner wouldn't flag it either because nothing in the view hierarchy is wrong. The only reason it got found is that I use VoiceOver all day and got sick of swiping back to my place, and then the testers wouldn't let it go. If nobody on your team lives on a screen reader, I'd bet you have one of these. You just haven't heard it yet.

Also, I should have timed it on day one. A second is a long time in software. Nothing that redraws a button takes a second. If I'd noticed that first I'd have skipped two builds and gone straight to the audio.

Build 48, with this fix, went to the TestFlight testers on September 27, 2026.

Blog Category