Skip to content

fix(ios): resolve threading issues and crash on dead links#198

Merged
kdroidFilter merged 3 commits intomasterfrom
fix/ios-threading-and-crash-safety
Apr 11, 2026
Merged

fix(ios): resolve threading issues and crash on dead links#198
kdroidFilter merged 3 commits intomasterfrom
fix/ios-threading-and-crash-safety

Conversation

@kdroidFilter
Copy link
Copy Markdown
Owner

Summary

  • Fix crash on dead links: defer _hasMedia = true until AVPlayerItem reaches readyToPlay status, preventing VideoPlayerSurface from creating a UIKitView + AVPictureInPictureController with an invalid player item that throws ObjC NSExceptions during Compose recomposition
  • Fix threading violations: move all Compose mutableStateOf mutations to the main thread — KVO observers now dispatch to main before writing state, notification observers use NSOperationQueue.mainQueue, metadata extraction happens only on readyToPlay
  • Remove unsafe ObjC property access: never access item.error, reasonForWaitingToPlay, or track properties from KVO callbacks — only read primitive/enum values (status, timeControlStatus)
  • Guard PiP creation: check isPictureInPictureSupported() before creating AVPictureInPictureController (throws NSException if unsupported)
  • Reduce main thread load: position update timer reduced from 60fps to 15fps
  • Implement error state: _error is now a proper mutableStateOf (was hardcoded to null)

Test plan

  • Play a valid video URL — verify playback, metadata, seeking all work
  • Play a dead/invalid URL — verify error snackbar appears, no crash
  • Play multiple videos in sequence — verify no stale state or observers
  • Test on simulator (no PiP support) — verify no crash
  • Test background/foreground transitions during playback
  • Verify subtitle overlay still works
  • Test loop and restart functionality

- Move all Compose state mutations to main thread (KVO observers,
  notification observers, metadata extraction)
- Defer _hasMedia=true until AVPlayerItem reaches readyToPlay,
  preventing UIKitView creation with an invalid player item
- Extract metadata only when item is ready, avoiding ObjC NSExceptions
  from accessing track properties on unloaded/failed assets
- Guard periodic time observer with readyToPlay status check
- Guard AVPictureInPictureController creation with isPictureInPictureSupported
- Reduce position update timer from 60fps to 15fps
- Use NSOperationQueue.mainQueue for all notification observers
- Implement _error state properly (was hardcoded to null)
Files picked via UIDocumentPickerViewController require security-scoped
access. Without calling startAccessingSecurityScopedResource(), AVPlayer
cannot read the file and playback silently fails.

- Call startAccessingSecurityScopedResource() in openFile() before
  passing the URL to AVPlayer
- Track the scoped file and call stopAccessingSecurityScopedResource()
  on cleanup
- Refactor openUri into openNsUrl for shared logic reuse
iOS cannot present a UIDocumentPickerViewController while a
ModalBottomSheet is still visible (stacked modals not supported).

Use a pendingPick flag + LaunchedEffect to launch the picker only
after the sheet is fully dismissed. Also revert the unnecessary
security-scoped resource access changes in VideoPlayerState.
@kdroidFilter kdroidFilter merged commit 0c5b18c into master Apr 11, 2026
10 checks passed
@kdroidFilter kdroidFilter deleted the fix/ios-threading-and-crash-safety branch April 11, 2026 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant