Shion のもくログ(旧: Shion の技術メモ)

使った技術のメモや、うまくいかなかった事とかを綴ります

PR

2022/09/10 ~ 2022/09/16 のもくもく日記

もくもく 前回までは

2022/09/03 ~ 2022/09/09 のもくもく日記 をご覧ください。

今回の目標

  • iOSDC に参加する
  • レシピの整備

途中経過

その1

結果的に3行ほどの英語を書くのに、3時間ほど使ってしまったorz

頭が硬いのかもしれない……

その2

何となくVSCode でSwift のテストコードを見てみたら、VSCode 上でテスト実行できるようになってる👀

※Swift Package で、macOS 上で試せた

その3

iOSDC 2022 にオフライン参加してみたw

旧来のAPI をSwift ベースへ置き換え

Swift が登場してから数年たった今でも、例えばNSString などのSwift 以前のものに触る機会があるかと思われます。 今回のiOSDC でそのうちのいくつかを書き換えられることを知ったので、メモしていこうと思います。

  1. 正規表現
  2. 暗号ライブラリ

まず正規表現ですが、Swift 5.7 から新しい文法が増えたようです。 Swift 5.7で変わる正規表現を試してみよう - Speaker Deck から引用すると、今までは下記のような感じだったようです。

let input = "My name is Taylor Swift"
let regex = try NSRegularExpression(
    pattern: "My name is (\\w+)",
    options: .caseInsensitive
)

let matches = regex.matches(
    in: input,
    options: [],
    range: NSRange(location: 0, length: input.utf16.count)
)

if let match = matches.first {
    let range = match.range(at: 1)
    if let swiftRange = Range(range, in: input) {
        let name = input[swiftRange]
    }
}

この記述で辛い点は下記が挙げられるようです。

  • try を使わないとNSRegularExpression インスタンスを生成できない
  • NSRegularExpression のコンストラクター引数pattern の指定を見ると、パターンはエスケープしたものを指定しないといけない
  • NSRange が必要
  • 正規表現のキャプチャ結果を取り出すのに``NSRange``` の変換とOptional binding が必要

追加された文法では下記のようにかけるので、上記の問題点を回避しつつ記述をスッキリさせることが出来ます。

let input = "My name is Taylor Swift"
let regex: Regex<(Substring, name: Substring)> = /My name is (.*)/.ignoresCase()

let matches = input.matches(of: regex)

if let match = matches.first {
    print(match.1)
}

ちなみにリテラル表記以外にもRegex builder という記述方法もあるようです。 さて、このスライドの最後では、実行速度の計測がされています。 結果はSwift 5.7 で追加された文法は従来のものより遅いらしいので、少し考慮したほうが良いかもです。

次は暗号ライブラリの話です。 ChaChaPoly and You, CryptoKit Explained - Speaker Deck から引用すると、今まではC 言語製のCryptography というライブラリを使っていたかと思いますが、iOS 13 からCryptoKit が追加されたみたいです。C 言語との連携を考えなくてよくなった分、使いやすくなったかもしれません。

非同期処理の考察

通信などの非同期処理を実装する際、Rx シリーズのライブラリを使うこともあるかと思いますが、個人的に下記のあたりが悩ましいなと考えています。

  • Rx シリーズのライブラリサイズは大きめで、アプリサイズが肥大化しがち → 体験談ベースで根拠が薄いですが、お仕事でそういった問い合わせがあったので
  • 思想に則ったメソッドが多く定義されているものの、実際に使うのはごく一部で済んでしまう
  • メジャーバージョンアップするとAPI がガッツリ変わることがあり、保守フェーズでその対応は辛い

なので、Rx を維持するのももちろんありですが、他の可能性を探したいなと思っています。 昨今ではSwift Concurrency などの標準ベース?が充実して来ている印象があるので、それらをメモしてこうと思います。

まずSwift Concurrency時代のリアクティブプログラミングの基礎理解 - Speaker Deck を参考に、Rx シリーズ等でやっていたことを整理すると下記になるかと思います。

UI 、ネットワーク、その他(センサー、カメラなど) を繋ぐ

スライドによると令和4年時点では、ライブラリの整備状況は下記のようになります。

実際の実装の雰囲気はSwift Concurrency時代のiOSアプリの作り方 - Speaker Deck が参考になるかと思われます。

最後にSwift Concurrency Next Step - Speaker Deck を読むと、体系だった説明や注意点が解説されているので、しっかり読み込むと良さそうです。

ローカルビルド時間の改善

ひと口にビルドと言っても、どこで実行するかで分類することが出来ます。

  • CI ビルド
  • ローカルビルド

普段の開発作業は主に「ローカルビルド」を使うので、このビルド時間を改善出来れば、開発体験も向上するかと思います。ということでその辺りを深堀するために下記の順に資料を読んでいくと良いかもです。

  1. Xcode が遅い! とにかく遅い!! 遅い Xcode をなんとかする方法 - Speaker Deck
    → 余談: タイトルコール(CV: 立木文彦さん) で「遅い」を連呼していたり、オンライン参加者のコメント弾幕がツボったw
  2. LINE iOSのビルド環境の変遷 / Changes in LINE iOS Build Environment - Speaker Deck

まずXcode が遅い! とにかく遅い!! 遅い Xcode をなんとかする方法 - Speaker Deck ですが、2つの原理的な話と1つの提案事項が取り上げられています。

原理的な問題 原因 対応策
ワークスペースを開いてビルドすると止まる Xcode バグ
(XCBBuildService)
Xcode 14 Beta 2 にアップデートする
(バグフィックスされたため)
たまに普段よりビルドが遅くなる clang 内部のllvm ロック機構バグ なし
(llvm コードにFIXME があるのでそれにコントリビュートする)

提案事項の方は外部ビルドツールのBazel を採用することが取り上げられています。Bazel はiOS だけでなく色々なプログラミング言語に対応したGoogle 製のビルドツールです。他の勉強会等で個人的に観測した範囲では、Android やAngular(※v13 以前はビルドキャッシュが使えなかったので重かった思い出があります) のビルドするために採用したということを聞いた気がします。

さてその詳細は次の資料をLINE iOSのビルド環境の変遷 / Changes in LINE iOS Build Environment - Speaker Deck を読み進めると良いかもです。ここではLINE さんが経験したBazel の知見が取り上げられています。

  • 良かったところ: ビルド時間が爆速になった
    → グラフを見ると約半分の時間になったっぽい
  • 辛いところ: メンテコストが爆上がりした
    • xcodebuild の維持も必要
      Bazel が未対応のXcode 新機能を利用する際に維持が必要になってくる
    • 多くのハックが必要
    • Debugging 体験が悪い
    • 学習コストが高い
      → 余談: 自分も試そうとしたのですが、どこから手をつけて良いか分からなかったです……
    • ライブラリ管理が大変
      → 特にXcodeGen の依存関係の構成が一致しないのは辛そうでした
    • Cache 管理が大変

上記と、普段の開発シーンのユースケースから、LINE さんはローカルでBazel を使うメリットは少ないと判断したみたいです。

ところで、2021年にM1 Max チップが登場したのですが、その影響はどのくらいだったのでしょうか?これもLINE さんは検証していて、M1 Max でのインクリメンタルビルドはBazel よりXcodeBuild の方がやや早かったようです。そこで開発作業者全員のMac をM1 Max に切り替えたみたいです。

話をまとめるとローカルビルド時間を改善するには下記アプローチを試すと良さそうです。

  • 開発環境をXcode 14 にアップデートする
    → 「ワークスペースを開いてビルドすると止まる」バグが修正されたため
  • M1 Max のMac に切り替える
    → XcodeBuild を使ったインクリメンタルビルドがそれなりに早くなったため

ここでは取り上げませんでしたが下記のアプローチも参考になるかもです。

  • 「家族アルバム みてね」を支えるビルド環境の改善 - Speaker Deck
    → ビルドフェーズの整理によるビルド時間の改善例が取り上げられています
  • クックパッドさんのマルチモジュール構成
    → ビルド対象を絞ることによる高速化が出来るかもです(特にユニットテスト)
    → 余談: マルチモジュールの構成が令和版にアップデートされて、ビルド時間が1分代になったらしく、めっちゃすごいことになってた🎉

その他

その4

とりあえず私物のWindows 11 にAmazon アプリストアアプリをインストールしたので、Windows Subsystems for Android のセットアップが出来たはずw

あとはこれを開発時にも使えるようにすれば、色々遊べるはず💪

Android Studio 上にWindows Subsystems for Android が表示されたので、たぶん行けるw

※ドキュメントにあったadb とかを設定して試しました https://learn.microsoft.com/ja-jp/windows/android/wsa/#connect-to-the-windows-subsystem-for-android-for-debugging

その5

DroidKaigi 2022 のアプリをWindows Subsystems for Android で動くことを確認できた🎉 ……えっと、さて、これをどうリポジトリに反映させよう🤔

Issue にするとすれば、タイムライン画面をマウスのスクロールするためのホイール操作した時に、タップ判定になって、詳細画面へ遷移しちゃうことかな これってWSA だからなのか、例えばChromebook で見たらどうなのかとかとか色々気になってきたw

ちなみに赤枠にあるアイコンをタップしてアプリ外ブラウザを起動したら、Windows 側のブラウザが起動したw

雑にDroidKaigi アプリのWSA (部分的な)サポートをするIssue を作ってみたけど、Issue の内容がピンぼけしてしまった…… https://github.com/DroidKaigi/conference-app-2022/issues/391

とりあえず、マウスホイールを使ったスクロールがACTION_DONW 判定されていることが分かった 多分これが原因でタップイベントになっちゃっているんだと思う ……さて、判定ってどこで調整できるんだ?

......ってawaitFirstDown のあとなんだから、そりゃdown イベント来るの普通じゃね? あれ?どこが足がかりになるのかさっぱりw

DroidKaigi のWSA サポートしようとした時にマウスホイールイベントがタップイベントになっちゃう件、Compose で頑張るんじゃなくて、素直にMainActivity でonGenericMotionEvent をオーバーライドすればいけるのでは説👀

後で試してみよっと💪

試したけどうまく行かんかった😇 今度はKaigiApp ファイル内のKaigiAppScaffoldState#onTimeTableClick を呼び出しているところを辿ってみるか……

Sessions ファイルのTimetable で"clickable" 設定していて、 Timetable ファイルのTimetable で"pointerInput" 設定している

……どちらかをコメントアウトすると、スクロールで画面遷移はしないように見えるから、ここなのか🤔

Sessions ファイルのTimetable に"pointerInteropFilter" 使ってログを見てみたのだけど、WSA でマウス操作しても指で操作したとみなされてるっぽいorz

……えっと、これはWindows Subsystem for Android の仕様なのか🤔

いや待てよ、今回のこの挙動で困ったのはDroidKaigi アプリのタイムテーブルのところで、それ以外の例えばセッション一覧では起きないように見えるから、これはアプリの問題🤔

謎と秋が深まる今日この頃w

(セッション一覧も同じようにログをとってみたら、CANCEL 扱いになっとる😇)

その6

CORS の"preflight" リクエストって何だろうと思ったら、飛行前の点検って意味だった👀 知らんかったw https://eow.alc.co.jp/search?q=preflight

今回の進捗

※関連SNS
PR