Hi, I have a question about Kotlin Int to Swift an...
# touchlab-tools
f
Hi, I have a question about Kotlin Int to Swift and SKIE
Copy code
//  On swift side is Int32 (OK)
    public var test: Int = 0

    // On swift side is SkieSwiftOptionalStateFlow<KotlinInt> (WHY?)
    private val _intNullValue = MutableStateFlow<Int?>(null)
    public val intNullValue: StateFlow<Int?> = _intNullValue

    //  On swift side is SkieSwiftStateFlow<KotlinInt> (WHY?)
    private val _intNotNullValue = MutableStateFlow(0)
    public val intNotNullValue: StateFlow<Int> = _intNotNullValue
So why the stateflow is not
SkieSwiftStateFlow<Int32>
? same thing for other integer types.
t
SKIE is currently not doing changes to how generic types are represented. When you have
StateFlow<Int>
in Kotlin, SKIE makes it available using
SkieKotlinStateFlow<Int>
which produces
SkieKotlinStateFlow<KotlinInt>
for Objective-C/Swift. Then we bridge that to
SkieSwiftStateFlow
, but
KotlinInt
has no direct bridging. So SKIE would have to manually map the type in runtime which has added complexity. This is on our list of possible features, but that list is long, so much to do 😄
f
I see, currently it’s kind of downgrade, as by default the Kotlin int is replaced by ObjC Int32 automatically, but when I’m using the StateFlow is not. So, I need to do the job manually, I don’t want to know I’m woking with KotlinType. Let’s wait and see 😄
t
Kotlin's
Int
is replaced by
Int32
only when it's not in places where
NSObject
type is required (generics, some lambdas etc)
f
Yes, I understand that case. I’m using it inside ViewModel, I don’t have this issue. I just want to avoid using KotlinType.
t
I might be misunderstanding. Is there a different solution that allows you to use
StateFlow
with
Int32
from Swift? We could take inspiration from it
f
Oh, my bad. Inside a Shared Kotlin ViewModel The Kotlin StateFlowInt is converted to a SkieSwiftStateFlowKotlinInt. If I’m using a directly a Kotlin Int, it’s converted to a ObjC int32_t, the compiler use the expected type.
t
I see, but then you can't observe its changes, so it's either
Int32
but no observation, or
KotlinInt
but observing, correct?
f
yes, a classical ViewModel
I don’t have this issue with String or Data Class, I didn’t try every type. but Int is a basic one.
t
All types that are not
NSObject
will behave this way. For example even Kotlin's
Unit
is translated to Swift's
Void
, but when it's used in generics it'll be
KotlinUnit
because Objective-C's
void
is a primitive, same as
int32
,
int64
,
float
etc. It's a limitation of Objective-C generics and pointers. For example the same problem is when you make that Kotlin
Int
in your VM into
Int?
. You'll now see
KotlinInt?
in Swift.
f
Oh, I see. I wrap an
Int
and an
Int?
inside a data class, I got the following :
Int32
and
KotlinInt?
t
Yeah, basically there's no way to represent
int32
that'd be nullable in Objective-C without making it an object (
NSObject
). In real Objective-C, we used to just put
NSNumber
where we needed nullable
int32
, but Kotlin's doing better by introducing
KotlinInt
so it's at least visible that it's supposed to be an Int and not any number. Although it's still backed by
NSObject
(and it's a descendant) so you can call
.floatValue
on
KotlinInt
instance and I'll convert it to
float
, which is weird but again, Objective-C legacy.
f
I hope the SwiftExport will make the things easier.
t
Some, yeah
But things like generics will be very different and possibly more difficult to use
f
Ok, then the main issue is about the Generic. Currently SwiftExport use
Int32
and
Int32?
, so no use of KotlinInt, which is great
t
Yeah, but even
Int32
is not great for Swift, where you'd want to use just regular
Int
. But that's a different discussion
f
Well, that’s fine, Good to know some limitation about the iOS dev experiences,
The main reason of the first question is, I’m working on a macro for wraping a Kotlin ViewModel into a SwiftUI Viewmodel I got something like this and the integer type was kind of problematic, but now I have a better understanding, I have fixed my issue 😄
Copy code
@sharedViewModel(ofType: MainScreenViewModel.self,
                 publishing:
                    (\.mainScreenUIState, MainScreenUIState.self),
                 (\.userId, String?.self),
                 (\.intNotNullValue, Int.self),
                 (\.intNullValue, Int?.self)
)
class MyMainScreenViewModel: ObservableObject {}