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

Kotlin/Nativeで作ってみるCLI, iOSアプリ

k-tomoyasu
September 24, 2019

Kotlin/Nativeで作ってみるCLI, iOSアプリ

Kotlin/Nativeで共通のモジュールを使うCLI, iOSアプリを作る
Kotlin愛好会 vol.15

k-tomoyasu

September 24, 2019
Tweet

More Decks by k-tomoyasu

Other Decks in Programming

Transcript

  1. ,PUJMO.VMUJ1MBUGPSN1SPKFDU .11 w 6*͸ڞ௨ԽͤͣϩδοΫ෦෼ͷΈڞ௨Խ͢Δ w +7. +4 /BUJWF w ,PUMJO/BUJWF

    w ,PUMJOίʔυ͔Β֤ϓϥοτϑΥʔϜͷόΠφϦΛग़ྗͰ͖Δ w ,PUMJO/BUJWF˩.VMUJQMBUGPSN1SPKFDU w FYQFSJNFOUBMGFBUVSF͕ͩຊ൪ಋೖͷ࿩΋ग़͖͍ͯͯΔ w ʮLPUMJONVMUJQMBUGPSNQSPEVDUJPOʯͰάάΔͱνϥϗϥ
  2. ,PUMJO/BUJWF$-* w HSBEMFͰϏϧυઃఆ w .11ͷͨΊͷ࡞ۀ͸΄΅HSBEMFͷઃఆ kotlin { macosX64("macos") { binaries

    { executable("ghkw") { entryPoint = 'com.github.ktomoyasu.ghkw.cli.main' } } } ΤϯτϦʔϙΠϯτͱͳΔؔ਺ΛΧελϜ ग़ྗ͞ΕΔόΠφϦͷϑΝΠϧ໊ΛΧελϜ ࢦఆ஋ͱsrcͷσΟϨΫτϦΛ߹ΘͤΔ
  3. ,PUMJO/BUJWF$-* w ґଘؔ܎ͷهड़ sourceSets { commonMain { dependencies { implementation

    rootProject.ext.kotlinCommon implementation rootProject.ext.coroutineCommon implementation rootProject.ext.serializationCommon implementation rootProject.ext.ktorClient implementation rootProject.ext.ktorClientJson implementation rootProject.ext.ktorClientLogger } } macosMain { dependencies { implementation rootProject.ext.coroutineNative implementation rootProject.ext.serializationNative implementation rootProject.ext.ktorClientNative implementation rootProject.ext.ktorClientCurl implementation rootProject.ext.ktorClientJsonNative implementation rootProject.ext.ktorClientNative implementation rootProject.ext.ktorClientLoggerNative } }
  4. ڞ௨Ϟδϡʔϧ suspend fun search(words: List<String>, token:String): Response sealed class Response

    { data class Success(val data: List<KeywordResult>): Response() data class Error(val e: Exception): Response() } w (JU)VC"1*ͷΫϥΠΞϯτΛ$-* J04ڞ௨ͷϞδϡʔϧͱ࣮ͯ͠ ૷͢Δ w "QJ$MJFOUΫϥε w TFBSDIͰ࣮ߦ݁Ռ3FTQPOTFΛฦ͢
  5. $-*ͷ࣮૷ fun main(args: Array<String>) = runBlocking { val token =

    getenv(ENV_TOKEN) ?.toKString() ?: "" when (val response = ApiClient().search(args.toList(), token)) { is Success -> { response.data.forEach { println("${it.keyword}\t${it.totalCount}") } } is Error -> { fprintf(stderr, response.e.message) exitProcess(1) } } }
  6. J04ΞϓϦHSBEMF w GSBNFXPSLΛग़ྗ͢ΔͨΊʹHSBEMFͰઃఆ 
 kotlin { if (project.findProperty("device") ?.toBoolean() ?:

    false) { iosArm64('ios') { binaries { framework { baseName = "GhkwClient" } } } else { iosX64('ios') { binaries { framework { baseName = "GhkwClient" } } } } …… } • framework໊ΛΧελϜ ࢦఆ஋ͱsrcͷσΟϨΫτϦΛ߹ΘͤΔ
  7. J04ΞϓϦHSBEMF w ґଘؔ܎Λهड़ 
 kotlin { …… sourceSets { ……

    iosMain { dependencies { implementation rootProject.ext.coroutineNative implementation rootProject.ext.serializationNative implementation rootProject.ext.ktorClientIos implementation rootProject.ext.ktorClientJsonNative implementation rootProject.ext.ktorClientNative implementation rootProject.ext.ktorClientLoggerNative } } } •
  8. ڞ௨Ϟδϡʔϧ suspend fun search(words: List<String>, token:String): Response sealed class Response

    { data class Success(val data: List<KeywordResult>): Response() data class Error(val e: Exception): Response() } w 4XJGU͔ΒͲ͏ݟ͑Δ͔ؾʹͳΔ෦෼ w TFBMFEDMBTT w TVTQFOEGVO
  9. case (let result as Response.Success): … case (let err as

    Response.Error): … default: fatalError("unknown case.") } w ໢ཏੑνΣοΫ͕Ͱ͖ͳ͍ w গ͠࿩୊ʹ͍͋͛ͯΔJTTVF͕͋ͬͨ w IUUQTHJUIVCDPN+FU#SBJOTLPUMJOOBUJWFJTTVFT w ͜ͷJTTVFࣗମ͸4XJGU0CK$ͰFOVNΛαϙʔτͯ͠΄͍͠ͱ ͍͏಺༰ɻͦͷதͰগ͠৮ΕΒΕ͍ͯΔఔ౓
  10. // Kotlinଆͷఆٛ fun searchAsync(words: List<String>, token: String): Deferred<Response> = GlobalScope.async(coroutineDispatcher)

    { search(words, token) } // Swiftଆͷݺͼग़͠ let task = client.searchAsync(words: words, token: token) task.invokeOnCompletion { _ in let response = task.getCompleted() HFU$PNQMFUFE ͕ฦ͢ͷ͸z"OZ z
  11. ίʔϧόοΫΛ౉͢ελΠϧ fun search(words: List<String>, token: String, callback: (List<KeywordResult>) -> Unit,

    onError: (Exception) -> Unit) { GlobalScope.launch(coroutineDispatcher) { when (val response = search(words, token)) { is Response.Success -> callback(response.data) is Response.Error -> onError(response.e) } } } w ੒ޭ࣌ͷ-JTU ࣦഊ࣌ͷ&YDFQUJPOΛίʔϧόοΫʹ౉࣮͢૷ w 4XJGUଆͰͷΩϟετ͸ແ͘ͳΔ w ଟ͘ͷίʔϧόοΫͷ࣮૷Λཁٻ͢Δ
  12. %SPJE,BJHJͷΞϓϩʔν w ,PUMJOଆ͔Β%FGGFSFEΛฦ͠ɺ4XJGUଆͰ3Y4XJGUͷ4JOHMFΛฦ͢ϝιο υΛFYUFOTJPOͰ࡞Δ // SwiftͰͷݺͼग़͠ίʔυ. asSingle͕extension function return ApiComponentKt.generateDroidKaigiApi()

    .getSessionsAsync() .asSingle(Response.self) .map { ResponseToModelMapperKt.toModel($0) } .catchError { throw handledKotlinException($0) } w 3Yಋೖ͍ͯ͠ΔΞϓϦͰҰ؏ͨ͠هड़͕Ͱ͖Δ w ߴػೳͳ"1* w 3Yಋೖ͕ඞཁ IUUQTRJJUBDPNUBLBIJSPNJUFNTEGCGDBBF