我正在尝试使用Compose Multiplatform来实现一个针对Android和iOS的应用程序。该应用程序包含一个Map,这部分应使用Android上的谷歌Map和iOS上的苹果Map每个平台实现。
我有一个Composable函数,它需要Android和iOS的特定平台实现
@Composable
expect fun MyMap(items: List<Item>, onItemClicked: (Item) -> Unit)
我看到的问题是MKMapViewDelegateProtocol.mapView
在Kotlin中可能非常模糊。但我不知道如何在KMP中实现该协议,以便它被iOS应用程序选中,我得到了pin selected事件。
目前,iOS实现如下所示
@Composable
actual fun MyMap(items: List<Item>, onItemClicked: (Item) -> Unit) {
UIKitView(
modifier = Modifier.fillMaxSize(),
factory = {
MKMapView().apply {
setDelegate(MKDelegate { annotation ->
annotation?.title?.let { title ->
val item = items.find { it.title == title }
onItemClicked(item)
} ?: onItemClicked(null)
})
}
},
update = {
val pins = items.map { item ->
val pin = MKPointAnnotation()
val coordinates = item.coordinates
pin.setCoordinate(CLLocationCoordinate2DMake(coordinates.latitude.coordinate, coordinates.longitude.coordinate))
pin.setTitle(vendingMachine.address)
pin
}
it.addAnnotations(pins)
}
)
}
图钉在Map上显示正确,但当用户选择图钉时,我没有收到来自代理的任何点击事件。
我试着像这样实现MKMapView.setDelegate
所需的MKMapViewDelegateProtocol
:
private class MKDelegate(
private val onAnnotationClicked: (MKPointAnnotation?) -> Unit
) : NSObject(), MKMapViewDelegateProtocol {
override fun mapView(mapView: MKMapView, didSelectAnnotationView: MKAnnotationView) {
val annotation = didSelectAnnotationView.annotation as MKPointAnnotation
onAnnotationClicked(annotation)
}
}
1条答案
按热度按时间8iwquhpp1#
在iOS世界中,名为
delegate
的字段通常存储对对象的弱引用-这意味着此对象不负责对象的生命周期,因此当对象被销毁时,该属性会自动设置为null。这样做是为了防止保留周期。请参阅this question以了解详细信息。如果您计划从Kotlin实现更多iOS功能,请查看一些关于自动引用计数(ARC)的文章。Kotlin有它自己的内存模型,但是当你从Kotlin代码创建ObjC对象时,它们遵循ObjC内存模型。
因此,当你用
setDelegate(MKDelegate ...
创建一个对象时,它会立即被销毁,因为这个对象引用没有存储在任何强引用中。你需要把它分开存放。例如,可以使用
remember
: