0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

watchOS アプリの実機ビルド・インストールが遅い原因が Xcode スキームだった話

0
Posted at

TL;DR

  • Apple Watch アプリの ⌘R が毎回異様に遅い場合、スキームのビルド対象に iOS コンパニオンアプリが含まれていないかをまず疑う
  • Watch アプリが iOS アプリに埋め込まれる構成(Embed Watch Content)だと、Xcode が自動生成したスキームに iOS アプリが入っていることがあり、Watch を実行するたびに iOS アプリのビルド → 再署名 → iPhone へのインストールまで走る
  • スキームから iOS アプリを外すだけで、ビルド対象が Watch App+Widget 拡張だけになり大幅に短縮できる
  • 残りの遅さ(iPhone 経由の無線転送)は watchOS の宿命だが、運用でかなり改善できる

環境

  • Xcode 17 / watchOS 26 / iOS 26
  • 構成: iOS アプリ+Watch アプリ(コンパニオン型・WKCompanionAppBundleIdentifier あり)+ WidgetKit コンプリケーション拡張

症状

Apple Watch 実機に向けて ⌘R すると、コードを数行変えただけでもビルド〜インストール完了まで体感で数分待たされる。シミュレータは普通なのに実機だけ遅い。

調査

アプリサイズは問題なかった

まずアプリ自体が太っていないかを確認。ソースもアセットも合計 100KB 程度で、転送量が問題になるサイズではなかった。

du -sh "MyApp Watch App"/*

ビルド設定も問題なかった

Debug 構成は以下の通りで、ここも健全。

  • DEBUG_INFORMATION_FORMAT = dwarf(dSYM 生成なし)
  • ONLY_ACTIVE_ARCH = YES
  • SWIFT_OPTIMIZATION_LEVEL = -Onone

犯人はスキームだった

xcshareddata/xcschemes/*.xcscheme を開いて BuildAction を見ると、Watch App スキームのビルド対象に iOS アプリが入っていた

<BuildActionEntries>
   <BuildActionEntry ...>
      <BuildableReference
         BuildableName = "MyApp Watch App.app"
         ... />
   </BuildActionEntry>
   <!-- ↓ これが余計 -->
   <BuildActionEntry ...>
      <BuildableReference
         BuildableName = "MyApp.app"
         BlueprintName = "MyApp"
         ... />
   </BuildActionEntry>
</BuildActionEntries>

iOS アプリは「Embed Watch Content」ビルドフェーズで Watch アプリを埋め込むため、iOS アプリ → Watch アプリのターゲット依存がある。この状態で Watch スキームに iOS アプリが入っていると、⌘R のたびに

  1. Watch App+コンプリケーション拡張のビルド
  2. iOS アプリ全体のビルド+Watch アプリの埋め込み+再署名
  3. ペア iPhone への iOS アプリのインストール
  4. iPhone 経由で Watch へアプリ転送(Bluetooth/WiFi)

が全部走る。Watch 側の開発では 2〜3 は不要な仕事。

依存の向きに注目すると、Watch アプリは iOS アプリに依存していない(依存しているのは iOS アプリの側)。だから Watch スキームから iOS アプリを外しても何も壊れない。

修正

Xcode の GUI なら Edit Scheme… → Build で iOS アプリの行を削除するだけ。.xcscheme を直接編集するなら、該当の BuildActionEntry ブロックを削除する。

修正後、ビルドされるターゲットが Watch App+拡張だけになったことを確認:

xcodebuild -project MyApp.xcodeproj -scheme "MyApp Watch App" \
  -destination 'platform=watchOS Simulator,name=Apple Watch SE 3 (44mm)' build 2>&1 \
  | grep -oE "in target '[^']+'" | sort -u
# in target 'MyApp Watch App'
# in target 'MyAppComplicationExtension'

注意点

  • iPhone 側のコードを変えたときだけ、iOS アプリのスキームで別途インストールする(どうせやる操作なので手間は増えない)
  • コンパニオンアプリは一度 iPhone に入っていれば、Watch の ⌘R ごとに再インストールされる必要はない。WCSession(WatchConnectivity)もコンパニオンが入ってさえいれば動く
  • Widget/コンプリケーション拡張のスキームにも同じように iOS アプリが紛れ込んでいることがあるので、ついでに確認するとよい

それでも残る遅さと対策

watchOS の実機インストールは必ずペア iPhone を経由して無線転送されるため、iPhone 直挿しの感覚には絶対にならない。ただし以下でかなり変わる。

対策 理由
iPhone を USB ケーブルで Mac に接続する ネットワーク経由デバッグだと Watch への転送が数倍遅くなる
Watch を充電器に載せて画面を点けたままにする 省電力状態だと転送・インストールが露骨に遅くなる
Edit Scheme → Run → Info の「Debug executable」をオフ watchOS はデバッガのアタッチだけで数十秒かかることがある。print デバッグで足りる日はオフが快適
初回の遅さは諦める Xcode・デバイス再起動直後はシンボル準備が走るため必ず遅い。2回目以降は速くなる

おまけ: スキームに残った亡霊参照にも注意

今回の調査中、iOS アプリのスキームに削除済みの StoreKit Configuration ファイルへの参照が残っているのも見つけた。

<StoreKitConfigurationFileReference
   identifier = "../../LocalStoreKitConfig.storekit">
</StoreKitConfigurationFileReference>

ファイルを消してもスキーム側の参照は自動では消えない。起動時の余計な構成読み込み(と失敗)の元になるので、機能を撤去したらスキームも掃除しよう。

まとめ

  • 「watchOS の実機が遅いのは仕様」と思い込む前に、スキームのビルド対象を確認する
  • Xcode が自動生成するスキームは、Watch アプリ作成時の構成によって iOS アプリを巻き込んでいることがある
  • 依存の向き(iOS → Watch であって逆ではない)を理解していれば、安心して外せる
  • 残る転送の遅さは USB 接続・充電器・デバッガ非アタッチで軽減する
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?