Upgrade to Pro — share decks privately, control downloads, hide ads and more …

既存のプロジェクトにKMMを導入するための対応策

 既存のプロジェクトにKMMを導入するための対応策

Flutter × Kotlin Multiplatform by CyberAgent #6
https://cyberagent.connpass.com/event/243404/

Youtube
https://youtu.be/baP7shKzEEE?t=3420

Twitter
#ca_flutter_kmm

Taiki Suzuki

April 27, 2022
Tweet

More Decks by Taiki Suzuki

Other Decks in Programming

Transcript

  1. Flutter × Kotlin Multiplatform by 2022/04/27 #6 #ca_ fl utter_kmm

    by Taiki Suzuki طଘͷϓϩδΣΫτʹ KMMΛಋೖ͢ΔͨΊͷରԠࡦ
  2. ͜Ε·ͰͷऔΓ૊Έ #ca_ fl utter_kmm +BO ɹɹ,..Λར༻ͯ͠ ɹɹɹɹ"QJ$MJFOUͷڞ௨ԽΛ։࢝ 'FC ɹɹ'MVUUFSY,..CZ$" .BS

    ɹɹ"QJ$MJFOUΛຊ൪؀ڥͰϦϦʔε /BUJWFνʔϜͰ "QJ$MJFOUͷΈΛӡ༻ "OESPJEɾJ04ͰΞϓϦϦχϡʔΞϧϓϩδΣΫτ
  3. ͜Ε·ͰͷऔΓ૊Έ #ca_ fl utter_kmm +BO ɹɹ,..Λར༻ͯ͠ ɹɹɹɹ"QJ$MJFOUͷڞ௨ԽΛ։࢝ 'FC ɹɹ'MVUUFSY,..CZ$" .BS

    ɹɹ"QJ$MJFOUΛຊ൪؀ڥͰϦϦʔε +VM ɹɹ.1&νʔϜൃ଍ ɹɹɹɹ .VMUJQMBUGPSN&OHJOFFSJOH /BUJWFνʔϜͰ "QJ$MJFOUͷΈΛӡ༻ "OESPJEɾJ04ͰΞϓϦϦχϡʔΞϧϓϩδΣΫτ
  4. ͜Ε·ͰͷऔΓ૊Έ #ca_ fl utter_kmm +BO ɹɹ,..Λར༻ͯ͠ ɹɹɹɹ"QJ$MJFOUͷڞ௨ԽΛ։࢝ 'FC ɹɹ'MVUUFSY,..CZ$" .BS

    ɹɹ"QJ$MJFOUΛຊ൪؀ڥͰϦϦʔε +VM ɹɹ.1&νʔϜൃ଍ ɹɹɹɹ .VMUJQMBUGPSN&OHJOFFSJOH 4FQ ɹɹϓϩδΣΫτߏ੒ͱ ɹɹɹɹΞʔΩςΫνϟͷઃܭ։࢝ /BUJWFνʔϜͰ "QJ$MJFOUͷΈΛӡ༻ "OESPJEɾJ04ͰΞϓϦϦχϡʔΞϧϓϩδΣΫτ
  5. ͜Ε·ͰͷऔΓ૊Έ #ca_ fl utter_kmm +BO ɹɹ,..Λར༻ͯ͠ ɹɹɹɹ"QJ$MJFOUͷڞ௨ԽΛ։࢝ 'FC ɹɹ'MVUUFSY,..CZ$" .BS

    ɹɹ"QJ$MJFOUΛຊ൪؀ڥͰϦϦʔε +VM ɹɹ.1&νʔϜൃ଍ ɹɹɹɹ .VMUJQMBUGPSN&OHJOFFSJOH 4FQ ɹɹϓϩδΣΫτߏ੒ͱ ɹɹɹɹΞʔΩςΫνϟͷઃܭ։࢝ +BO ɹɹϚΠϦετϓϩδΣΫτ ɹɹɹɹ,..Λར༻ͯ͠։ൃ։࢝ /BUJWFνʔϜͰ "QJ$MJFOUͷΈΛӡ༻ "OESPJEɾJ04ͰΞϓϦϦχϡʔΞϧϓϩδΣΫτ
  6. ͜Ε·ͰͷऔΓ૊Έ #ca_ fl utter_kmm +BO ɹɹ,..Λར༻ͯ͠ ɹɹɹɹ"QJ$MJFOUͷڞ௨ԽΛ։࢝ 'FC ɹɹ'MVUUFSY,..CZ$" .BS

    ɹɹ"QJ$MJFOUΛຊ൪؀ڥͰϦϦʔε +VM ɹɹ.1&νʔϜൃ଍ ɹɹɹɹ .VMUJQMBUGPSN&OHJOFFSJOH 4FQ ɹɹϓϩδΣΫτߏ੒ͱ ɹɹɹɹΞʔΩςΫνϟͷઃܭ։࢝ +BO ɹɹϚΠϦετϓϩδΣΫτ ɹɹɹɹ,..Λར༻ͯ͠։ൃ։࢝ .BS ɹɹϚΠϦετΛϦϦʔε /BUJWFνʔϜͰ "QJ$MJFOUͷΈΛӡ༻ "OESPJEɾJ04ͰΞϓϦϦχϡʔΞϧϓϩδΣΫτ
  7. iOS Android iOS-MPP ,.. ϓϩδΣΫτߏ੒ͱΞʔΩςΫνϟ (2021 NovҎલ) #ca_ fl utter_kmm

    ApiClient Protobuf w ϦΫΤετͨ͠63-ͷϨεϙϯεΛQSPUPCVGͰฦ͢ w (JU)VC1BDLBHFTͰBSUJGBDUΛఏڙ
  8. iOS Android ,.. ApiClient Protobuf iOS-MPP ϓϩδΣΫτߏ੒ͱΞʔΩςΫνϟ (2021 NovҎલ) #ca_

    fl utter_kmm w ෳ਺ͷϞδϡʔϧΛJ04޲͚ʹͭʹ·ͱΊΔϞδϡʔϧ w (JU)VC3FMFBTFTͰYDGSBNFXPSLΛఏڙ
  9. iOS ,.. ApiClient Protobuf Android iOS-MPP ϓϩδΣΫτߏ੒ͱΞʔΩςΫνϟ (2021 NovҎલ) #ca_

    fl utter_kmm JNQMFNFOUBUJPO BQJDMJFOUBQJDMJFOU "OESPJEͱJ04͕ผϦϙδτϦʹͳ͓ͬͯΓ ͦΕͧΕͰར༻͍ͨ͠όʔδϣϯΛࢦఆ JNQMFNFOUBUJPO BQJDMJFOUBQJDMJFOU
  10. ϓϩδΣΫτߏ੒ͱΞʔΩςΫνϟ (2021 NovҎ߱) #ca_ fl utter_kmm iOS Android iOS-MPP ApiClient

    Protobuf core apiservice core repository service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper groups apiservice groups repository groups usecase groups usecase I/F groups domain ,..
  11. ,.. iOS Android iOS-MPP ApiClient Protobuf core apiservice core repository

    service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper groups apiservice groups repository groups usecase groups usecase I/F groups domain ػೳ͝ͱͷ୯Ґͷgroups #ca_ fl utter_kmm w HSPVQTYYYͷػೳ͝ͱͷ୯ҐͷTVCQSPKFDU
  12. ,.. iOS Android iOS-MPP ApiClient Protobuf core apiservice core repository

    service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper groups apiservice groups repository groups usecase groups usecase I/F groups domain ػೳ͝ͱͷ୯Ґͷgroups #ca_ fl utter_kmm groups apiservice groups repository groups usecase groups usecase I/F groups domain groups apiservice groups repository groups usecase groups usecase I/F groups domain groups apiservice groups repository groups usecase groups usecase I/F groups domain 'FBUVSF 
 ಛू .ZMJTU ϚΠϦετ 4FBSDI ݕࡧ 4MPU(SPVQ 
 ์ૹ࿮άϧʔϓ
  13. ,.. iOS Android iOS-MPP ApiClient Protobuf core apiservice core repository

    service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper groups apiservice groups repository groups usecase groups usecase I/F groups domain ֤moduleͷ಺༰ #ca_ fl utter_kmm w EPNBJOPCKFDU w BQJTFSWJDFJOUFSGBDF w SFQPTJUPSZJOUFSGBDF w SFQPTJUPSZJOUFSGBDFͷ࣮૷ w VTFDBTFNPEFM w VTFDBTFJOUFSGBDF w VTFDBTFJOUFSGBDFͷ࣮૷ w EPNBJOPCKFDU͔ΒVTFDBTFNPEFM΁ͷϚοϐϯά w BQJTFSWJDFJOUFSGBDFͷ࣮૷ w QSPUPCVG͔ΒEPNBJOPCKFDU΁ͷϚοϐϯά
  14. ,.. iOS Android iOS-MPP ApiClient Protobuf core apiservice core repository

    service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper groups apiservice groups repository groups usecase groups usecase I/F groups domain groupsͷartifactͷ؅ཧ #ca_ fl utter_kmm w HSPVQTYYYͷػೳ͝ͱͷ୯ҐͷTVCQSPKFDU w ࠨਤͷϞδϡʔϧΛ؅ཧ w ػೳ͝ͱʹಉ͡HSPVQ*EɾWFSTJPOͰBSUJGBDUΛఏڙ
  15. #ca_ fl utter_kmm (JU)VC"1* (JU)VC $* HSPVQTGFBUVSFͷमਖ਼13ΛNBJOʹϚʔδ GFBUVSFYYYͷUBHΛ੾Δ GFBUVSFYYYͷSFMFBTFTΛ࡞੒ HSPVQTGFBUVSFͷ֤ϞδϡʔϧͷΈΛϏϧυ

    HSPVQTGFBUVSFͷ֤ϞδϡʔϧΛ HSPVQTGFBUVSFYYYYYYͷBSUJGBDUͱͯ͠ (JU)VC1BDLBHFTʹΞοϓϩʔυ ػೳ͝ͱͷartifactͷ഑෍ྫ
  16. ,.. service
 interface groups repository ApiClient Protobuf core apiservice core

    repository service domain mapper core
 domain usecase
 model usecase
 mapper groups apiservice groups usecase groups usecase I/F groups domain iOS Android iOS-MPP ֤ΞϓϦ͔Βͷࢀর #ca_ fl utter_kmm JNQMFNFOUBUJPO NZMJTUEPNBJO  JNQMFNFOUBUJPO NZMJTUBQJTFSWJDF  ʜ JNQMFNFOUBUJPO TFBSDIEPNBJO  JNQMFNFOUBUJPO TFBSDIBQJTFSWJDF  ʜ JNQMFNFOUBUJPO NZMJTUEPNBJO  JNQMFNFOUBUJPO NZMJTUBQJTFSWJDF  ʜ JNQMFNFOUBUJPO TFBSDIEPNBJO  JNQMFNFOUBUJPO TFBSDIBQJTFSWJDF  ʜ "OESPJEͱJ04͕ผϦϙδτϦͳͷͰɺػೳ։ൃͷ ਐḿʹࠩ෼͕͋ͬͯ΋ڐ༰Ͱ͖ΔΑ͏ʹ͢Δ
  17. ,.. iOS Android iOS-MPP ApiClient Protobuf groups apiservice groups repository

    groups usecase groups usecase I/F groups domain ڞ௨ͷ΋ͷΛ·ͱΊͨcore #ca_ fl utter_kmm core apiservice core repository service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper w ڞ௨Ͱར༻͞ΕΔ΋ͷ͕·ͱ·ͬͨ୯ҰͷTVCQSPKFDU w ӈਤͷϞδϡʔϧΛ؅ཧ
  18. ,.. iOS Android iOS-MPP ApiClient Protobuf groups apiservice groups repository

    groups usecase groups usecase I/F groups domain ֤Ϟδϡʔϧͷ಺༰ #ca_ fl utter_kmm core apiservice core repository service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper w EPNBJOPCKFDU w BQJTFSWJDFJOUFSGBDF w SFQPTJUPSZJOUFSGBDF w BQJTFSWJDFJOUFSGBDFͷ࣮૷ w SFQPTJUPSZJOUFSGBDFͷ࣮૷ w QSPUPCVG͔ΒEPNBJOPCKFDU΁ͷϚοϐϯά w TFSWJDFJOUFSGBDFͷ࣮૷ w EPNBJOPCKFDU͔ΒVTFDBTFNPEFM΁ͷϚοϐϯά w VTFDBTFͰڞ௨Ͱར༻͞ΕΔ΋ͷΛදݱͨ͠JOUFSGBDF w VTFDBTFNPEFM
  19. ,.. iOS Android iOS-MPP ApiClient Protobuf groups apiservice groups repository

    groups usecase groups usecase I/F groups domain coreͷartifactͷ؅ཧ #ca_ fl utter_kmm core apiservice core repository service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper w ڞ௨Ͱར༻͞ΕΔ΋ͷ͕·ͱ·ͬͨ୯ҰͷTVCQSPKFDU w ӈਤͷϞδϡʔϧΛ؅ཧ w DPSF഑ԼΛಉ͡HSPVQ*EɾWFSTJPOͰBSUJGBDUΛఏڙ
  20. ,.. iOS Android iOS-MPP ApiClient Protobuf groups apiservice groups repository

    groups usecase groups usecase I/F groups domain groupsͷcore΁ͷґଘ #ca_ fl utter_kmm core apiservice core repository service service
 interface domain mapper core
 domain usecase
 model usecase
 mapper 'FBUVSF .ZMJTU 4FBSDI 4MPU(SPVQ FUD ֤ػೳ HSPVQ ͕ґଘ͍ͯ͠ΔͨΊ ޙํޓ׵Λอ࣮ͬͨ૷ʹ͢Δඞཁ͕͋Δ
  21. ,.. core repository service usecase
 model usecase
 mapper groups repository

    groups usecase service
 interface iOS Android iOS-MPP groups usecase I/F groups domain domain mapper core
 domain ApiClient Protobuf groups apiservice apiservice͕ଘࡏ͢Δཧ༝ #ca_ fl utter_kmm core apiservice ଞͷϓϥοτϑΥʔϜͰ΋"QJ$MJFOU͕ར༻Ͱ͖Δঢ়ଶʹ͢ΔͨΊ ϞόΠϧΞϓϦ޲͚ͷEPNBJOʹґଘͨ͠BQJTFSWJDFΛఆ͍ٛͯ͠Δ
  22. KMMΛར༻ͨ͠৽ػೳ։ൃ #ca_ fl utter_kmm • ϚΠϏσΦɾ௨஌༧໿ΛϚΠϦετʹू໿͢ΔϓϩδΣΫτ • KMMଆʹண໨ͨ͠։ൃମ੍ @marty_suzuki w

    ,..ͷج൫੔උ w ։ൃதʹ໰୊͕ൃੜͨ͠ࡍͷରԠ @ronnnnn_jp w ,..ͷج൫੔උ w "OESPJEͷ࣮૷୲౰ @akkyie w ϚΠϦετͷઃܭ w J04ͷ࣮૷୲౰ w 6*ͷରԠ w طଘͷमਖ਼౳ w 6*ͷରԠ w طଘͷमਖ਼౳
  23. ج൫ଆͰࣄલʹରԠ༧ఆͩͬͨ΋ͷ #ca_ fl utter_kmm ΞϓϦଆͰطʹ࣮૷͞Ε͍ͯΔRepository౳ΛɺKMMͷ۩ମ࣮૷ͷ UseCase͔Βݺͼग़ͯ͠ར༻Ͱ͖ΔΑ͏ʹ͢Δ class SomeUseCaseImpl( private val

    userRepository: UserRepository ) { fun someFunction() { userRepository.observeUserId() } } KMM protocol UserRepository { var userID: Property<User.ID?> { get } } iOS interface UserStore { val userId: StateFlow<String> } Android
  24. UserRepositoryΛAndroidͰద߹͢Δ #ca_ fl utter_kmm interface UserRepository { fun observeUserId(): Flow<UserId?>

    } KMM class UserRepositoryImpl( private val userStore: UserStore, ) : UserRepository { override fun observeUserId(): Flow<UserId?> { return userStore.userId .map { UserId(string = it) } } } Android ϦΞʔΩςΫνϟதͰ'MVYͷ࣮૷͕࢒͍ͬͯΔͨΊ 
 4UPSFΛϥοϓ͢ΔܗͰద߹͢Δ
  25. UserRepositoryΛiOSͰద߹͢Δ #ca_ fl utter_kmm class UserRepository: KMM.UserRepository { let userID:

    Property<User.ID?> func observeUserId() -> Kotlinx_coroutines_coreFlow { ... } } iOS interface UserRepository { fun observeUserId(): Flow<UserId?> } KMM طଘͷ6TFS3FQPTJUPSZͷ࣮૷ʹ,..ଆͷ 6TFS3FQPTJUPSZΛద߹͢Δ 'MPX͸JOUFSGBDF͕ͩɺ0CKFDUJWF$ͷQSPUPSPMͰ͸ܕύϥϝʔλʹ ରԠ͍ͯ͠ͳ͍ͨΊɺܕύϥϝʔλ͕ফࣦ͢ΔͷͰλΠϓΞϯηʔϑ
  26. UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm abstract class FlowCompat<T>( protected open val

    base: Flow<T> ) { open fun toFlow(): Flow<T> = base } class MutableStateFlowCompat<T> private constructor( override val base: MutableStateFlow<T> ) : FlowCompat<T>(base) { constructor(value: T) : this(MutableStateFlow<T>(value)) override fun toFlow(): Flow<T> = base.asStateFlow() fun send(value: T) { base.value = value } } KMM/iosMain DMBTTͰ͋Ε͹0CKFDUJWF$ͷ-JHIUXFJHIU(FOFSJDT͕ ར༻Ͱ͖ΔͨΊɺ'MPXΛϥοϓ͢Δ J04Ͱఆ͍ٛͯͨ͠1SPQFSUZ͸ঢ়ଶΛอ͍࣋ͯ͠ΔͨΊ'MPX$PNQBU ʹద߹ͨ͠4UBUF'MPXΛϥοϓͨ͠ΫϥεΛఆٛ
  27. UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm interface UserRepositoryInterface { fun observeUserId(): FlowCompat<UserId?>

    } class UserRepositoryTranslator( private val userRepository: UserRepositoryInterface ) : UserRepository { override fun observeUserId(): Flow<UserId?> { return userRepository.observeUserId().toFlow() } } KMM/iosMain 6TFS3FQPTJUPSZ*OUFSGBDFͷॲཧΛ6TFS3FQPTJUPSZ޲͚ʹ ม׵͢ΔΞμϓλΛఆٛ 'MPX5Ͱ͸ͳ͘ɺJ04޲͚ʹ'MPX$PNQBU5Λར༻͢ΔJOUFSGBDFΛ 
 6TFS3FQPTJUPSZͱಉҰͷཻ౓Ͱఆٛ
  28. UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm class UserRepository: KMM.UserRepositoryInterface { let userID:

    Property<User.ID?> func observeUserId() -> FlowCompat<UserId> { ... } } let usecase = KMM.SomeUseCaseImpl( userRepository: KMM.UserRepositoryTranslator( repository: UserRepository() ) ) iOS 6TFS*EܕͷΈΛड͚෇͚ΔΑ͏ʹͳͬͨͷͰλΠϓηʔϑʹ 6TFS3FQPTJUPSZ*OUFSGBDFʹద߹ͨ͠ΫϥεΛ6TFS3FQPTJUPSZ5SBOTMBUPSΛ ʹ౉ͯ͠ɺ಺෦ͷม׵ॲཧΛհ͢Δ͜ͱͰ,..ͷ6TFS3FQPTJUPSZʹద߹Ͱ͖Δ
  29. class UserRepository: KMM.UserRepositoryInterface { let userID: Property<User.ID?> func observeUserId() ->

    FlowCompat<UserId> { ... } } let usecase = KMM.SomeUseCaseImpl( userRepository: KMM.UserRepositoryTranslator( repository: UserRepository() ) ) iOS UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm ,..Ͱఏڙ͞ΕΔΦϒδΣΫτ͸ɺܕύϥϝʔλ͕"OZ0CKFDUͰ ͳ͚Ε͹͍͚ͳ͍͕ɺ4XJGUͷ0QUJPOBM͸FOVNͰ͋ΔͨΊফࣦ͢Δ
  30. UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm sealed class Nullable<T : Any> {

    class Null<T : Any>: Nullable<T>() data class Nonnull<T : Any>(val value: T): Nullable<T>() fun toDefault(): T? = when (this) { is Null -> null is Nonnull -> value } } KMM/iosMain /VMMBCMFΛJ04޲͚ͷ໌ࣔతͳܕͱͯ͠ఆٛ͠ ,..ଆͰ͸,PUMJOͷ/VMMBCMFʹ໭ͤΔΑ͏ʹ͢Δ
  31. UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm interface UserRepositoryInterface { fun observeUserId(): FlowCompat<Nullable<UserId>>

    } class UserRepositoryTranslator( private val userRepository: UserRepositoryInterface ) : UserRepository { override fun observeUserId(): Flow<UserId?> { return userRepository.observeUserId().toFlow() .map { it.toDefault() } } } KMM/iosMain 'MPX6TFS*E Λ'MPX$PNQBU/VMMBCMF6TFS*EͰఆٛ͠ ۩ମ࣮૷Ͱ͸UP%FGBVMU Λݺͼग़ͯ͠'MPX6TFS*E ʹ໭͢
  32. UserRepositoryΛiOSͰద߹ͤ͞ΔͨΊʹ #ca_ fl utter_kmm class UserRepository: KMM.UserRepositoryInterface { let userID:

    Property<User.ID> private let mutableUserID = MutableStateFlowCompat<Nullable<UserId>>( value: NullableNull() ) init() { userID.asObservable() .subscribe(onNext: { [mutableUserID] id in let id = id.map { NullableNonnull(value: UserId(string: $0)) } ?? NullableNull() mutableUserID.send(value: id) }) .disposed(by: disposeBag) } func observeUserId() -> FlowCompat<Nullable<UserId>> { mutableUserID } } iOS J04Ͱ΋/VMMBCMFͱͯ͠,..ଆʹ౉ͤΔΑ͏ʹͳΔ
  33. ܨ͗ࠐΈ࣌ʹ՝୊ʹͳͬͨ͜ͱ #ca_ fl utter_kmm interface SomeUseCase { fun display(): LoadableResult<SomeUseCaseModel>

    } sealed class LoadableResult<out R> { object Loading : LoadableResult<Nothing>() data class Loaded<R>(val result: R) : LoadableResult<R>() } KMM
  34. Android͔Βݺͼग़͢৔߹ #ca_ fl utter_kmm val usecase: SomeUseCase = ... when

    (val loadableResult = usecase.display()) { LoadableResult.Loading -> { // handle loading } is LoadableResult.Loaded<SomeUseCaseModel> -> { loadableResult.result // handle loaded } } Android ໢ཏతʹ෼ذ͕Ͱ͖ɺͦΕͧΕͷॲཧ͕Ͱ͖Δ
  35. iOS͔Βݺͼग़͢৔߹ #ca_ fl utter_kmm let usecase: SomeUseCase = ... let

    loadableResult = usecase.display() if loadableResult is LoadableResultLoading { // handle loading } else if let loaded = loadableResult as? LoadableResultLoaded { loaded.result // handle loaded } else { assertionFailure("might not reach this line") } iOS ໢ཏతʹ෼ذͰ͖ͳ͍ͨΊɺΠϨΪϡϥʔέʔεͷߟྀ͕ ίʔυ্ඞཁʹͳͬͯ͠·͏ ͨͩͷ-PEBCMF3FTVMUͷαϒΫϥεʹͳͬͯ͠·͏ͷͰ -PBEJOHͱ-PBEFEΛΩϟετͯ͠൑ఆ͢Δ͔͠ͳ͍
  36. iOSͰ໢ཏతʹ෼ذͰ͖ΔΑ͏ʹ͢Δ #ca_ fl utter_kmm sealed class LoadableResult<out R> { object

    Loading : LoadableResult<Nothing>() data class Loaded<R>(val result: R) : LoadableResult<R>() fun <T> fold( onLoading: (LoadableResult.Loading) -> T, onLoaded: (LoadableResult.Loaded<out R>) -> T ): T = when (this) { is LoadableResult.Loading -> onLoading(this) is LoadableResult.Loaded -> onLoaded(this) } } KMM/iosMain ,PUMJOͷ3FTVMUͰ࣮૷͞Ε͍ͯΔ4VDDFTTͱ'BJMVSFΛ ల։ͯ͠೚ҙͷܕʹม׵͢ΔGPMEؔ਺ͷΑ͏ͳରԠ https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/#extension-functions
  37. #ca_ fl utter_kmm loadableResult.fold( onLoading: <#(LoadableResultLoading) -> Any?#>, onLoaded: <#(LoadableResultLoaded<SomeUseCaseModel>)

    -> Any?#> ) <# -> Any?#> iOS iOSͰ໢ཏతʹ෼ذͰ͖ΔΑ͏ʹ͢Δ 0CKFDUJWF$ͷ-JHIUXFJHIU(FOFSJDT͸ؔ਺ͷܕύϥϝʔλʹରԠ͍ͯ͠ͳ͍ ͷͰɺ,..ଆͰఆٛͯ͠΋J04Ͱ͸"OZʹͳͬͯ͠·͏
  38. #ca_ fl utter_kmm class LoadableResultFold<out R, out T : Any>(

    value: LoadableResult<R>, onLoading: (LoadableResult.Loading) -> T, onLoaded: (LoadableResult.Loaded<R>) -> T ) { val result: T = when (value) { is LoadableResult.Loading -> onLoading(value) is LoadableResult.Loaded -> onLoaded(value) } } KMM/iosMain iOSͰ໢ཏతʹ෼ذͰ͖ΔΑ͏ʹ͢Δ 0CKFDUJWF$ͷ-JHIUXFJHIU(FOFSJDTͰΫϥεͷܕύϥϝʔλ͸ར༻Ͱ͖ΔͷͰ ໢ཏతʹ෼ذΛͯ͠ม׵͢ΔͨΊͷΫϥεΛఆٛ͢Δ
  39. #ca_ fl utter_kmm final class Box<T> { let value: T

    init(_ value: T) { self.value = value } } let value: SomeUseCaseModel? = LoadableResultFold( value: loadableResult, onLoading: { _ in Box<SomeUseCaseModel?>(nil) }, onLoaded: { Box<SomeUseCaseModel?>($0.result) } ).result.value iOS iOSͰ໢ཏతʹ෼ذͰ͖ΔΑ͏ʹ͢Δ ܕύϥϝʔλ͸"OZ0CKFDUͰͳ͚Ε͹͍͚ͳ͍ͨΊɺ#PYܕ౳ͰϥοϓΛͯ͠ 
 ,..Ͱఏڙ͞Ε͍ͯΔܕΛऔΓग़ͤΔΑ͏ʹ͢Δ
  40. #ca_ fl utter_kmm • iOSͰ͸sealed classΛ໢ཏతʹ෼ذͰ͖ͳ͍ • enumͰ΋ಉ༷ͷ͜ͱ͕ى͖Δ • Objective-CͷLightweight

    GenericsͰදݱͰ͖ΔൣғͰରԠ • foldΛࣗಈੜ੒͢Δ͜ͱͰɺ্هͷ໰୊Λղܾ ໢ཏతʹ෼ذ͢Δ