如何在 KMM(kotlin 本机)共享模块中读取 Swift 框架库中生成的对象数组

Posted

技术标签:

【中文标题】如何在 KMM(kotlin 本机)共享模块中读取 Swift 框架库中生成的对象数组【英文标题】:How to read an array of objectes generated in a Swift framework library, in a KMM (kotlin native) shared module 【发布时间】:2021-06-10 05:00:13 【问题描述】:

我正在开发一个 KMM 应用程序。共享模块有一个帮助类,它依赖于 android 部分和 ios 部分的不同本地库。这是通过已知的“预期/实际”模式实现的。

如前所述,iOS 实际类使用了一个 iOS 框架,它执行一些计算并返回一个对象数组。创建对象列表的 ios 框架可以正常工作(通过单元测试进行了测试)。下面是一个简化的示例。

这是数组内对象的类:

public class ChildNodeIos:  NSObject

public  let content:String
public let isTextNode:Bool

public init(content:String,isTextNode:Bool=false)
    self.content=content
    self.isTextNode=isTextNode

iOS 端返回对象列表的帮助器类是这样的:

@objc public class IOSCoolHelper: NSObject 
    @objc public func getChildNodes(message: String) -> [ChildNodeIos]  
       //build the array of child nodes here and return them
     

在 kotlin 共享模块中,在 iOS 预期类中,函数调用如下:

@Serializable
data class ChildNodeKN(val content :String,val isTextNode :Boolean=false)

import com.mydomain.iosframeworks.IosCoolHelper
actual class CoolHelper actual constructor(private val someStuff: String)  : ICoolHelper 

       actual override fun getChildNodes(message: String): List<ChildNodeKN> 
            val iosHelper= IOSCoolHelper()
            val swiftarray:List<ChildNodeIos>  = iosHelper.getChildNodes(message)
    
            //I was expecting to do something like that but it does not work (the content of "array is always empty"):
    
            val kotlinList:List<ChildNodeKN> = swiftarray as List<ChildNodeIos>
    
         return kotlinList
    
        
    
    

或者,如果 swift 对象列表不能直接转换为等效的 kotlin 对象列表,我希望能够遍历 swift 列表并将其转换为 kotlin 列表,如下所示:

    val kotlinList=mutableListOf<ChildNodeKN>()
swiftArray.foreach
kotlinList.add(ChildNodeKN(it.content,it.isTextNode))

但同样,swift Array 的内容是空的。做了很多测试(我现在无法重现它们),我设法访问了数组中的一些东西,但它不是 ChildNodeIos 类型的对象,也不是我在 kotlin 端读不到的东西。

好吧,问题是,如何在 kotlin 端接收 iOS 端生成的内部或多或少复杂对象的列表?

我不得不说,这个 swift helper 类还有许多其他返回原始值(字符串、布尔值或 int)的函数,而且效果很好。

我想一个解决方法是使用一个包含对象的数组,从 Swift 端返回一个包含原始类型和二维的数组,但如果可能的话,我想使用一个对象数组。

感谢您的帮助

【问题讨论】:

【参考方案1】:

我自己设法找到了解决方案。问题在于列表中包含的对象的 Swift 类的声明。我忘记了类属性的@objc 声明,因为如果那样我就无法读取返回数组中的对象。

公共类 ChildNodeIos: NSObject

@objc  public  let content:String
@objc  public let isTextNode:Bool

public init(content:String,isTextNode:Bool=false)
    self.content=content
    self.isTextNode=isTextNode

然后,在 Kotlin 方面,我没有实现将其直接转换为列表,但是使用 foreach 循环很容易在 Kotlin 对象中编写 iOS 对象:

【讨论】:

以上是关于如何在 KMM(kotlin 本机)共享模块中读取 Swift 框架库中生成的对象数组的主要内容,如果未能解决你的问题,请参考以下文章

KMM:如何将共享模块引用到现有的 iOS 项目中

不学Flutter,我们来用Kotlin KMM跨平台吧

如何在 iOS 项目中添加两个或多个 kotlin 原生模块

KMM(Kotlin Multiplatform Mobile)环境搭建

KMM(Kotlin Multiplatform Mobile)环境搭建

KMM(Kotlin Multiplatform Mobile)环境搭建