2024.10.21
お互い疑心暗鬼になりがちな、経営企画と事業部の壁 組織に「分断」が生まれる要因と打開策
リンクをコピー
記事をブックマーク
鈴木大貴氏:次の項目に進みます。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.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.21
40代〜50代の管理職が「部下を承認する」のに苦戦するわけ 職場での「傷つき」をこじらせた世代に必要なこと
2024.11.20
成果が目立つ「攻めのタイプ」ばかり採用しがちな職場 「優秀な人材」を求める人がスルーしているもの
2024.11.20
「元エースの管理職」が若手営業を育てる時に陥りがちな罠 順調なチーム・苦戦するチームの違いから見る、育成のポイント
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.19
がんばっているのに伸び悩む営業・成果を出す営業の違い 『無敗営業』著者が教える、つい陥りがちな「思い込み」の罠
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.15
好きなことで起業、赤字を膨らませても引くに引けない理由 倒産リスクが一気に高まる、起業でありがちな失敗
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.21
40代〜50代の管理職が「部下を承認する」のに苦戦するわけ 職場での「傷つき」をこじらせた世代に必要なこと
2024.11.20
成果が目立つ「攻めのタイプ」ばかり採用しがちな職場 「優秀な人材」を求める人がスルーしているもの
2024.11.20
「元エースの管理職」が若手営業を育てる時に陥りがちな罠 順調なチーム・苦戦するチームの違いから見る、育成のポイント
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.19
がんばっているのに伸び悩む営業・成果を出す営業の違い 『無敗営業』著者が教える、つい陥りがちな「思い込み」の罠
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.15
好きなことで起業、赤字を膨らませても引くに引けない理由 倒産リスクが一気に高まる、起業でありがちな失敗