简体   繁体   中英

Mappings and usage of Kotlin data types and Swift data types

Let's say I have a function foo which takes two arguments:

actual fun foo(list1: List<Long>, list2: List<Double>) {
...
}

According to the https://kotlinlang.org/docs/tutorials/native/apple-framework.html Kotlin's Long type is mapped to KotlinLong and Kotlin's Double is mapped to KotlinDouble . Now I would like to call this function from my iOS App. Let's say I have two arrays:

let list1Numbers = [1000.43, 564121.34, 5617172172.234, 100.7]
let list2Numbers = [2.1, 3.2, 1.7]

For the list2 I could do something like:

let list2NumbersKotlin = list2Numbers.map({KotlinDouble.init(double: $0)})

which is not very convenient but will work. The list1 is a bit more problematic. Since there is no Long in Swift, I do something like

let list1NumbersKotlin =  list1Numbers.map({KotlinLong.init(longLong: Int64($0))})

Questions:

  1. Is there a better way to do it?

  2. What is a typical approach to deal with such types mapping when using Kotlin as an iOS Framework? Unfortunately I couldn't find any examples on the Internet.

  3. Should certain types such as Long be completely avoided if I want to use Kotlin as iOS Framework?

  4. Also, regarding mapping in general: since the Kotlin function

     fun testDouble(testVal: Double) {}

allows me to pass in Swift the Double directly:

HelloKt.testDouble(testVal: Double)

then why does the function

fun testList(testList: List<Double>) {}

not allow me to enter Double array but requires a KotlinDouble array?

HelloKt.testList(testList: [KotlinDouble]){}

Passing a [Double] gives error:

Cannot convert value of type '[Double]' to expected argument type '[KotlinDouble]'

  1. There are multiple ways.

You are talking about collections of data that are on the line between primitive types and objects, which tends to be a special case in Kotlin anyway.

Speaking to that, in Kotlin, you might want a LongArray and a DoubleArray rather than List<Long> and List<Double> . Coming from Swift, you'll be forced to explicitly box them. Kotlin will handle that for you when you're writing Kotlin code, but they're still getting boxed under the hood.

So, summary, either what you've done above, or take LongArray and DoubleArray as args rather than lists, and do a different translation. Either way, you will need to move the data into something Koltin compatible.

Obviously, if you put that in a helper function, ugly as it perhaps may be, you only need to do it once.

  1. Either your method or what I described.

  2. Long isn't problematic. There is a "long" in Swift, it's Int64 . Having to wrap values like that isn't fun, but Kotlin and Swift are different languages, and there are compromises. If you use Int in Kotlin instead of Long , you'll need to wrap a Swift Int with Int32 . A Kotlin Int is, in that sense, "problematic" in the same way. You need to specify which precision int you're using.

  3. In Kotlin, List<Long> is a list of Long objects, while just a Long is a primitive value. Kotlin hides the boxing of those values, but they are boxed. The Swift/Kotlin interface is forcing you to be more explicit. If you want primitive values, use the ___Array forms mentioned above.

Here is the mapping list between Kotlin and Swift types:

https://kotlinlang.org/docs/apple-framework.html#kotlin-numbers-and-nsnumber

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM