onseok / peekaboo

🌄 Kotlin Multiplatform library for Compose Multiplatform, designed for seamless integration of an image picker feature in iOS and Android applications.
Apache License 2.0
237 stars 20 forks source link

Pekaboo crashes on iOS with "startRunning may not be called between calls to beginConfiguration and commitConfiguration" #91

Open shtolik opened 4 months ago

shtolik commented 4 months ago

There were crashes on iOS devices when retaking images again and initialCameraMode is passed to rememberPeekabooCameraState.

Not on every image retake, but quite often. I was able to reproduce the problem by adding it into sample code of camera setup in this repo as well. val state = rememberPeekabooCameraState(initialCameraMode = cameraMode, onCapture = onCapture) where cameraMode is passed as variable to PeekabooCameraView (i think it wasn't crashing if i just set locally initialCameraMode = CameraMode.Back, but not sure).

That's the crash description

** Terminating app due to uncaught exception 'NSGenericException', reason: '*** -[AVCaptureSession startRunning] startRunning may not be called between calls to beginConfiguration and commitConfiguration'

And then debug breakpoint is activate in the place below.

PeekabooCamera.ios.kt
...

@OptIn(ExperimentalForeignApi::class)
@Composable
private fun RealDeviceCamera(
    state: PeekabooCameraState,
    camera: AVCaptureDevice,
    modifier: Modifier,
) {
....
    UIKitView(
        modifier = modifier,
        background = Color.Black,
        factory = {
            val dispatchGroup = dispatch_group_create()
            val cameraContainer = UIView()
            cameraContainer.layer.addSublayer(cameraPreviewLayer)
            cameraPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
            dispatch_group_enter(dispatchGroup)
            dispatch_async(queue) {
-- crash break point -->                captureSession.startRunning()
                dispatch_group_leave(dispatchGroup)
            }

So I stopped passing that variable in my app and I think it helped, but need to test on more device - so there is a workaround, but would be great to fix it.

shtolik commented 4 months ago

So it may not be this camerMode related, still crashes without setting it on ios quite often:(

nickfaces commented 2 months ago

@shtolik

In PeekabooCamera.ios.kt try change this

        dispatch_group_enter(dispatchGroup)
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.toLong(), 0UL)) {
            captureSession.startRunning()
            dispatch_group_leave(dispatchGroup)
        }
        captureSession.commitConfiguration()

        dispatch_group_notify(dispatchGroup, dispatch_get_main_queue()) {
            onCameraReady()
        }

to

        captureSession.commitConfiguration()

        dispatch_async(queue) {
            captureSession.startRunning()

            dispatch_async(dispatch_get_main_queue()) {
                state.onCameraReady()
            }
        }