`Uncaught Kotlin exception: kotlin.IllegalStateExc...
# compose-ios
s
Uncaught Kotlin exception: kotlin.IllegalStateException: Currently, UIKitViewController cannot be used within Popups or Dialogs
hi is this available to use? if so in which version?
m
I use iOS Alert dialogs on my Compose Multiplatform Apps since first versions of Compose:
Copy code
val alert = UIAlertController.alertControllerWithTitle(...)

LocalUIViewController.current.showViewController(alert, null)
How are you using it?
s
I am trying to use the AVPlayer within compose multiplatform bottomsheet
m
Well, I created a Compose function to wrap the iOS BottomSheet:
Copy code
@Composable
fun NativeBottomSheetImpl(
    onDismissRequest: () -> Unit,
    modifier: Modifier,
    sheetState: SheetState,
    content: @Composable ColumnScope.() -> Unit
) {
    val scope = rememberCoroutineScope()
    val controller = LocalUIViewController.current

    val colorScheme = MaterialTheme.colorScheme
    val shapes = MaterialTheme.shapes
    val typography = MaterialTheme.typography

    val bottomSheetViewController = remember {
        UIViewControllerWrapper(onDismissRequest, ComposeUIViewController {
            MaterialTheme(
                colorScheme = colorScheme,
                shapes = shapes,
                typography = typography
            ) {
                Surface(
                    modifier = Modifier.fillMaxSize()
                ) {
                    Box(
                        modifier = modifier.padding(top = 30.dp)
                    ) {
                        Column(
                            modifier = modifier,
                            content = content
                        )
                    }
                }
            }
        })
    }

    bottomSheetViewController.sheetPresentationController?.run {
        this.detents = ...
        this.largestUndimmedDetentIdentifier = ...
        this.prefersScrollingExpandsWhenScrolledToEdge = ...
        this.prefersEdgeAttachedInCompactHeight = ...
        this.widthFollowsPreferredContentSizeWhenEdgeAttached = ...
        this.prefersGrabberVisible = ...
    }

    DisposableEffect(Unit) {
        controller.presentViewController(bottomSheetViewController, animated = true) {
            scope.launch { sheetState.show() }
        }
        onDispose {
            if (controller.presentedViewController == bottomSheetViewController) {
                onDismissRequest.invoke()
                bottomSheetViewController.dismissViewControllerAnimated(flag = true, completion = null)
            }
        }
    }
}

@OptIn(ExperimentalForeignApi::class)
private class UIViewControllerWrapper<T : UIViewController>(
    private val onDismissRequest: () -> Unit,
    val child: T,
) : UIViewController(null, null) {
    override fun viewDidLoad() {
        super.viewDidLoad()
        addChildViewController(child)
        child.view.setFrame(view.frame)
        view.addSubview(child.view)
        child.didMoveToParentViewController(this)
    }

    override fun viewDidDisappear(animated: Boolean) {
        super.viewDidDisappear(animated)
        onDismissRequest.invoke()
    }
}