Making Reading Progress Predictable

Resume only feels useful when the saved position behaves the same after every kind of exit.

The problem

A reader can pause, finish a document, background the app, or leave the reader screen. Each path needs to save a position, and a completed document needs to start from the beginning when someone chooses to read it again.

// Before: interruption was not part of the save path
func handleInterruption() {
    speech.pause()
    // The current offset could disappear with the session.
}

The change

Textway Reader now persists the live offset on pause, completion, interruption, backgrounding, and exit. The playback state stays explicit: Reading aloud, Paused,Interrupted, Ready to continue, orFinished. I also added tests for async loading and interruption state, then wired those checks into the Fastlane build lane used by GitHub Actions.

// After: persist interruption progress and reset finished documents
.onChange(of: speech.isInterrupted) { _, interrupted in
    if interrupted { saveProgress() }
}

let startOffset = document.playbackOffset(for: text.utf16.count)
speech.play(text: text, from: startOffset, speed: speed, voiceIdentifier: voiceID)
Start at saved offsetUpdate while speakingPersist on exitResume laterReset after finish

Result

Progress is now one rule instead of several slightly different rules. The project still stops short of restoring playback after the process is killed, and full interruption testing is better on a physical device than in the Simulator.

← Back to all articles