【问题标题】:Kotlin Mutliplatform : Maping Swift/Objc code to Kotlin in iOSMain module?Kotlin Multiplatform:将 Swift/Objc 代码映射到 iOS 主模块中的 Kotlin?
【发布时间】:2022-09-23 05:44:23
【问题描述】:

我正在学习 KMM。我现在正在 iOSMain 和 Android main 中设计一个通用的位置获取

我的问题是,我不知道在 iOSMain 中将 Swift 映射到 Kotlin

例如,

获取位置的 Swift 代码是

var locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
var currentLoc: CLLocation!
if(CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
CLLocationManager.authorizationStatus() == .authorizedAlways) {
   currentLoc = locationManager.location
   print(currentLoc.coordinate.latitude)
   print(currentLoc.coordinate.longitude)
} 

Kotlin 端实现:

在上面的代码中:

  1. 如何在 Kotlin 代码中使用 Swift 的 .authorizedWhenInUse.authorizedAlways

  2. 而在 currentLoc.coordinate.longitudelongitudelatitude 没有解决。为什么 ?

    请帮我

    标签: android ios swift kotlin kotlin-multiplatform


    【解决方案1】:

    将 Swift (Objective-C) 映射到 Kotlin

    1. 如何在 Kotlin 代码中使用 Swift 的 .authorizedWhenInUse 和 .authorizedAlways ?

      根据Kotlin's documentation on interoperability,Kotlin/Native 提供与 Objective-C 而不是 Swift 的双向互操作性,所以我的第一个建议是参考 Apple 的 Objective-C 文档通过 Swift 文档。

      如果你打开Swift documentation for .authorizedWhenInUse,你会看到你可以将语言切换到Objective-C:


      将其切换到 Objective-C documentation 以查看如何在 Objective-C 中引用它:


      鉴于此,您应该能够在 Kotlin 代码中使用 kCLAuthorizationStatusAuthorizedWhenInUse

      引用 iOS 框架

      由于您已经有一些参考代码,您还可以简单地使用 Command+Click(或 Command+B)其中一个对象(例如,CLLocationManager)来打开已编译的 Kotlin 代码。

      您也可以手动从 Android Studio 的“项目”视图→“外部库”访问所有 iOS 框架,然后搜索您要搜索的 iOS 框架。

      在这里,您可以挖掘框架以找到您要查找的内容。不知道等效的 Objective-C API,您可以搜索“authorizedWhenInUse”并找到它:

      处理 C 结构

      1. currentLoc.coordinate.longitude ,经纬度不解析

      这个比较复杂...

      location 属性的类型是 CLLocationCoordinate2D 并且(重要的部分!)是它包含在 CValue 中:

      @kotlinx.cinterop.ExternalObjCClass public open class CLLocation : platform.darwin.NSObject, platform.Foundation.NSCopyingProtocol, platform.Foundation.NSSecureCodingProtocol {
      
          ...
      
          public final val coordinate: kotlinx.cinterop.CValue<platform.CoreLocation.CLLocationCoordinate2D> /* compiled code */
      
      

      请注意,在 Objective-C 中,CLLocationCoordinate2D is a C struct

      typedef struct CLLocationCoordinate2D {
          ...
      } CLLocationCoordinate2D;
      

      The Kotlin documentation here is thin, but it shows the methods available for CValue includes the .useContents() method

      因此,您的代码可以编写如下(编译并确认它运行并在物理设备上生成位置):

      val locationManager = CLLocationManager()
      
      val currentLoc: CLLocation?
      if (locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse ||
          locationManager.authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
          currentLoc = locationManager.location
      
          currentLoc?.coordinate?.useContents {
              println("latitude = ${latitude}")
              println("longitude = ${longitude}")
          }
      }
      

      [2022 年 9 月更新]如果你想深入挖掘,我还发表了一篇关于使用 Kotlin 和 KMM 的期望/实际编写 iOS 平台相关代码的博客文章:artandscienceofcoding.com/science/avoid-this-kmm-technique

    【讨论】:

    • [主观编辑] 这种复杂性是我(作为一名经验丰富的 iOS 工程师)更喜欢用 Swift 编写本机代码并避免在我的 KMM 项目中编写“Kotlin 化”的 Objective-C 代码的原因。
    • 哇。很棒的答案也消除了我未来的疑虑。非常感谢@DerekLee 对图片的详细回答
    • 我的荣幸!我会留意您可能遇到的任何其他 KMM 问题。 ??
    • @RagAnt,我不太确定我是否理解您的问题。从我在 Android Studio 中看到的情况来看,iOS 框架(我认为在历史上是 Objective-C)暴露给 Kotlin,您可以在 External Libraries -> "Kotlin/Native 1.6.20 - Framework" 下进行验证,例如CoreGraphics、HealthKit、MediaPlayer、UIKit 等。Cocoapods 是用于集成 3rd 方开源框架的单独工具,但是,我不使用 Cocoapods,所以很抱歉我无法评论该集成如何与 Kotlin/Native 一起工作。
    • 哇。很棒的文章。等待第二部分(因为已经在 Swift 中尝试过这种方法,而且更好)。非常感谢您记得我并通知我,因为我的公司要求我为同事开设 KMM 课程。通过你在适当的时候得到了一些好的源材料。谢谢@DerekLee
    猜你喜欢
    • 2021-03-24
    • 2016-05-27
    • 2021-02-16
    • 1970-01-01
    • 2020-04-28
    • 2021-07-12
    • 1970-01-01
    • 2019-08-26
    • 2021-03-19
    相关资源
    最近更新 更多