2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
リンクをコピー
記事をブックマーク
鈴木大貴氏:次の項目に進みます。mockやfakeなどテストのときだけ必要なものなど任意のモジュールをimportしたいという需要はあると思います。
KMMの構成です。moduleAというかたちでKMMのプロジェクト側で定義されたときに、iOSKMM.framworkというフレームワークが1個生成されます。
モジュールが複数あった場合は、そのモジュールをまとめるモジュールを1つ用意して、まとめたモジュールをビルドすればiOSのフレームワークとして出力できます。
さらにそこに対してmockなどテストのときにしか使いたくないモジュールを別なモジュールとして定義して、それにアプリ側で使うものを紐づければ、2つのフレームワークとしてKMMのフレームワークとmockのフレームワークを生成できます。
ここで注意しないといけないのが、KMMのmockのフレームワークに対してiOSのもともとのKMMのフレームワークがリンクされていないということです。iOSKMMMockでiOSKMMをimportしている状態にはなっていないです。
実際にフレームワークから見ると、まったく同じものを別モジュールとしてビルドしたものが、それぞれできあがるというかたちです。
なので、例えばApiClientというクラスがmoduleAにそれぞれあったとしても、iOSKMMとiOSKMMMockでは型が別なものという扱いになります。
今回はCocoaPodsを使ってこれを取り込んでいるので、これは妥協案なんですが、iOSのconfigurationのRelease向きかDebug向きかというもので設定ができます。
テストするときには基本的にDebug configurationを利用して、ストアにリリースするときのアプリに対してはRelease configurationを利用します。そのconfigurationで紐づけるフレームワークを変えることで、一応利用できます。
厳密に言うと、テストのときだけ利用したいものをimportするのではなくて、開発のときにだけテストで利用するものも含められるようにするという対策をしています。
この方法じゃなくても、テストターゲットのビルド時にリンクするフレームワークを変更するスクリプトを書けば使えなくはないのですが、そのままCocoaPodsの機能として使っています。
その延長で、実際にKMMのフレームワークをCocoaPodsのプライベートリポジトリのReleasesにアップロードして利用できるようにする方法です。
公式でアナウンスされているものは、native.cocoapodsというプラグインを入れて、Gradleの設定ファイルの中にCocoaPodsの設定を書いて、それらを同一の階層にいるものとみなしてpathで指定して取得するという方法です。
ビルドしたものを都度iOS側で取り込むのではなくて、リンクされたものをスクリプトでビルドしてiOS側で参照します。
今回実現している方法はそうではなくて、Kotlin Multiplatformで生成したものをzipでプライベートリポジトリのReleasesにアップロードをして、Podspecを自分自身で定義して、それをプライベートなSpecsにアップロードして、Xcodeから取り込む場合には、CocoaPodsでPrivate SpecのPodspecを指定して実際の成果物をダウンロードするというものです。
これを通常使うPodspecの定義で定義すると、このようにダウンロードのzipのリンクを定義することになると思います。プライベートリポジトリのReleasesだとWebサイト上はアクセスできるんですが、実際にそのリンクから直接アクセスしようとすると、認証状態だったとしてもそもそもアクセスするURLが違うのでエラーになってしまいます。
なので、すごく長くなっちゃうんですが、さっきの定義していた部分がこの赤い部分だとして、Podspec自体が定義ファイルではなくて実質Rubyのコードを書けるスクリプトになっているので、assetのURLを取得するものを含むかたちにしています。
動きとしてどうなっているかというと、podのrepo pushでプライベートなspecsにpushします。specの中で実際にGitHubのAPIに該当tagの情報を取りに行って、そのReleasesの情報の中から該当するzipファイルの名前を取得して、そのassetのURLを取得してspecのsourceの中に入れるという処理をしています。
これは疑似的な定義ですが、先ほどの長い定義ファイルの中で外側から見えるのはこのsourceで、GitHubのassetsのダウンロード先のURLが取得できます。
そのままアクセスするとzipではなくて、JSONとして定義の情報を取ってくるだけなので、application/octet-streamをheaderで指定して、typeはzipで取ってきます。
Private Specのテンプレート自体はGistで公開されているので、ぜひ見てもらえればと思います。
ちょっと多いんですが、Releasesを利用するときの注意点を簡単に上から話します。pod installのときにspec自体はインストール可能な状態なんですが、lintをかけようとするとvalidationのエラーになるというものがあるので、現在はそれを実行しない方法で対策を取っています。
外部のFacebook SDKでもspecのlintを試してみたらエラーになったので、これはおそらくまだ修正されていない問題なんじゃないかなと思っています。
ダウンロードするときにはGitHubのACCESS_TOKENが必要になんですが、pushのオプションで--use-jsonを使うとACCESS_TOKENが先ほどのJSONファイルに書き込まれてしまうので、netrcを使って認証するのをおすすめします。
また、xcftameworkを使うと実際にリンク可能なものでもpod repo push時に内部で走っているlinkerのテストでエラーになる場合があるので、importのvalidationとtestをskipすることで現状はいったん回避しています。
あとpod installの時に実際にpodでpushしたときもnetrcかGITHUB_ACCESS_TOKENを使っていた場合にはどちらかを利用しなければなりません。ここまでがCocoaPodsの導入の仕方です。
最後に、あまり該当する人はいないとは思いますが、Kotlinで実装されたNSObjectのサブクラスをSwizzleするとクラッシュするという問題があります。
サードパーティのフレームワークなどで、iOSだとSwizzlingという、もともと定義されているメソッドを書き換えるものがあるんですが、それが使われているとクラッシュするということが発生しています。
これはkotlin-nativeの1.4.30では直ってはいるので、バージョン的に使えないという方向けに説明します。参考の実装として、APIを通信する部分でktorというものを使っています。
ktorにはIosResponseReaderというものが実装されていて、それがNSObjectのサブクラス、かつURLのDelegateを実装しています。
Delegateのメソッドがこのようなかたちで4つほど定義されています。このメソッドがパフォーマンス計測などでSwizzlingされることがあります。
これらがIosClientEngineというもので実際にktorの中で定義されているんですが、iOSのNSURLSessionをKotlin側で初期化されたときにresponseReaderをDelegateとして渡す状態で使われています。
responseReader自体がinternalで定義してあるので、なにか修正を加える場合にはforkして対応するか、そのままコピーして修正を加えるかの方法でしか対策は取れなくなります。
今回の例に関しては、Swift側でURLSessionのinitializer自体をswizzleできれば、Kotlin側のサブクラスをswizzleすることにはならないので、delegate自体を入れ替えます。
swizzleをして、クラスの名前がKotlinに関連しているktorのものだったら入れ替えをして、1個ラップしたdelegateで実装します。
delegateの実際の内容は、先ほど定義したdelegateメソッドをもう1度Swiftで定義し直して、実際にKotlinに定義されているものを1個ラップして、愚直にメソッドをもう1度呼び直すというものです。
直接Kotlin側で定義されたNSObjectのswizzleが走るわけではないので、クラッシュを回避できます。これはiOSのswizzleするときのメソッドです。
私からはiOSに導入する部分でいろいろと話をしました。ご清聴ありがとうございました。
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05