LoginSignup
1
0

Kotlin Multiplatformのobject型がSingletonになる

Posted at

まずはコード

全てのコードは一番簡略的抽象化して一部切り抜けたもの

kmp側

abstract class Event : Parcelable {
    var id: String = UUID.randomUUID()
        internal set
}
sealed class EventBase : Event {
    object EventB : Event()
    data class EventA(name: String) : Event()
    ...
}

var event: Event


event = Event.EventA(name = "000")
event = Event.EventB
event = Event.EventB

Swift

public protocol StateMachineInterface {
    associatedtype EventType
    var event: Observable<EventType> { get }
}
var instance: StateMachineInterface ... // (eventをKMPから受け取る)

var event: Observable<EventType> { 
    return instance.map { 
        $0.event 
    }
    .asObservable()
    .observe(on: scheduler)
    .share(replay: 1, scope: .whileConnected)
}

event
    .distinctUntilChanged {
        print("compare \($0),\($1)") // 調査するためにログを仕込んだ
        return $0.id == $1.id
    }
    .subscribe {
        print("subscribe \($0)")
        ...
    }
    ...

出力結果

subscribe EventA(id=uuid1, name=000)
compare EventA(id=uuid1, name=000),EventB(id=uuid2)
subscribe EventB(id=uuid2)
compare EventB(id=uuid3),EventB(id=uuid3)

疑問

この出力結果でいくつかの疑問点が出てきます。

  • EventBが連続で流れた場合subscribeに辿り着かない
  • distinctUntilChangedのbeforeとafterが1eventで同時に変更されている

解明

調べた末、Kotlin Multiplatformのobject型がiOS用にコンパイルされた時SingletonになることがKMPの公式に書いてあった
https://kotlinlang.org/docs/native-objc-interop.html#kotlin-singletons
WX20231226-210018@2x.png

これだけ知っていれば先ほどの挙動に解釈がつく

  • EventBはobject型で宣言されているため、idだけが変わって実際はずっと同じinstance
  • SingletonだからRxswiftの内部で参照型copy作ろうとしても結局同じinstanceが登録される
  • EventBが連続で来たらbeforeとafterは同じaddressなので、afterのidが変わったらもちろんbeforeも一緒に変わる

結論

KMP使うならiOSエンジニアも一緒にKotlin勉強しましょう

参考リンク

https://kotlinlang.org/docs/object-declarations.html#object-declarations-overview
https://kotlinlang.org/docs/native-objc-interop.html#kotlin-singletons

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0