(edit: remove irrelevant stuff) hi folks, did anyo...
# multiplatform
v
(edit: remove irrelevant stuff) hi folks, did anyone use an objC selector function from Kotlin via cinterop? I’m trying to monitor an iPhone’s orientation changes in a CMP project, I wrote a custom delegate for my
ComposeUIViewController
which looks like this:
Copy code
@ExportObjCClass
@OptIn(ExperimentalForeignApi::class, BetaInteropApi::class)
class MyComposeUIViewControllerDelegate : ComposeUIViewControllerDelegate {

    override fun viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter.addObserver(
            observer = this,
            selector = NSSelectorFromString("orientationDidChange"),
            name = UIDeviceOrientationDidChangeNotification,
            `object` = null
        )
    }

    @ObjCAction
    fun orientationDidChange(notification: NSNotification) {
        Log.w("###") { "orientation changed" }
    }
}
It always crashes with an
'NSInvalidArgumentException', reason: '-[ComposeAppMyComposeUIViewControllerDelegate orientationDidChange]: unrecognized selector sent to instance
. The root cause seems to be that the
orientationDidChange
method somehow gets an invalid / mismatching signature in objC. I’ve tried adding a colon when passing the selector like`NSSelectorFromString("orientationDidChange:"),` adding an
@ObjCName("orientationDidChange")
annotation to the method, to no avail. I suppose there is a bug somewhere in the cinterop layer, but before I move on raising an issue, does anyone have any further idea?
🧵 1
b
Hi, not sure whether you need detect orientation change moment, but I use next approach to decide how to place compositions according screen orientation
Copy code
fun ScreenSizeInfo.getScreenOrientation(): ScreenOrientation {
    return if (widthDP > heightDP) ScreenOrientation.LANDSCAPE else ScreenOrientation.PORTRAIT
}
iOS implementation for getting ScreenSizeInfo:
Copy code
actual fun getScreenSizeInfo(): ScreenSizeInfo {
    val density = LocalDensity.current
    val config = LocalWindowInfo.current.containerSize

    return ScreenSizeInfo(
        heightDP = with(density) { config.height.toDp() },
        widthDP = with(density) { config.width.toDp() }
    )
}
P.S. Divers thread 😅
v
hey fellow diver 😄 to elaborate: I need the orientation change event. In my app (which is edge-to-edge), I switch from BottomNavigation in portrait to a NavigationRail in landscape. My approach to handling the issue when the rail overlaps with the camera cutout: detect on which side the camera is currently located and display the rail at the opposite side. That was quite trivial on both iOS and Android, e.g. for Android:
Copy code
actual fun getPhysicalCameraPosition(): LandscapeCameraPosition =
    when (getCurrentDisplay()?.rotation) {
        Surface.ROTATION_90 -> LandscapeCameraPosition.LEFT
        Surface.ROTATION_270 -> LandscapeCameraPosition.RIGHT
        else -> LandscapeCameraPosition.UNSPECIFIED
    }
The problem: there is no automatic recomposition when the device (no matter which OS) is rotated by 180 degrees, as opposed to a 90 deg rotation. So I had to trigger it on my own by mutating a state. For Android, I solved this using the
DisplayManager.DisplayListener
and for iOS, I want to use the approach described in my post. Indeed I could do the detection in Swift and then call some Kotlin code, but my preferred approach would be Kotlin-only.
👍 1