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:
Is there a better way to do it?
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.
Should certain types such as Long be completely avoided if I want to use Kotlin as iOS Framework?
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]'
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.
Either your method or what I described.
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.
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.