mcpField
C
capacitor-uiscene-migration

capacitor-uiscene-migration

github.com/cap-go開発7354 回インストール2 週間前に更新
リポジトリ

capacitor-uiscene-migration について

Xcode 27 の要件に対応するため、Capacitor iOS プロジェクトを AppDelegate のライフサイクルから UIScene へ移行するスキルです。移行状態、独自のライフサイクル処理や URL 処理、ビルドと実行時の検証を扱います。

主な機能

  1. 01UIScene の移行状態を判定
  2. 02ライフサイクルと URL 処理を監査
  3. 03AppDelegate と SceneDelegate の変更を案内
  4. 04プラグインと SDK のライフサイクル確認
  5. 05ビルドとアプリ動作の検証

活用シーン

  1. 01Capacitor 8.4 以前を Xcode 27 に備える
  2. 02cap migrate の部分移行結果への対処
  3. 03シーン導入後のディープリンク維持
  4. 04プラグインの UIScene 互換性確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cap-go/capgo-skills --skill capacitor-uiscene-migration

インストール後、Claude Code で/capacitor-uiscene-migrationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

metadata.json
references/
audit-patterns.md
pbxproj-registration.md
plugin-audit.md
scene-delegate-template.md

詳細

Capacitor UIScene への移行(8.4 -> 8.5)

Capacitor 8.5 では、Xcode 27 で必要となるため、iOS テンプレートが UIScene ライフサイクルに移行しました。これは iOS のみを対象とした、破壊的変更を含むマイナーリリースです。8.5 のコアは引き続き AppDelegate の経路で動作するため、依存関係を更新しただけでアプリが壊れることはありません。Xcode 27 でビルドするには(また、Capacitor 9 にアップグレードする前に)、アプリのプロジェクトでシーンを採用する必要があります。

正式な情報源:https://capacitorjs.com/docs/updating/8-5

使用する状況

次の場合に使用します:

  • アプリが @capacitor/ios 8.0~8.4 を使用している場合、または 8.5 を使用しているものの、Info.plist に UIApplicationSceneManifest がない場合
  • Xcode 27 のビルド時または実行時に、「CLIENT OF UIKIT REQUIRES UPDATE: This process does not adopt UIScene lifecycle」という警告が表示される場合
  • npx cap migrate の実行時に UIScene migration: project is in a partial state ... Skipping automated migration と表示された場合
  • シーンマニフェストを追加した後、カスタム URL スキーム、ユニバーサルリンク、appUrlOpen、または AppDelegate の applicationDidBecomeActive のコードが実行されなくなった場合
  • 8.5 への更新後、tmpWindow または TmpViewController でビルドエラーが発生した場合
  • プラグインの作成者から、iOS コードがシーンライフサイクルでも動作するか質問された場合
  • 8.4 以前から Capacitor 8 -> 9 へのアップグレードを準備している場合

使用しない状況:

  • Capacitor 8 -> 9 のパッケージ/ネイティブのアップグレード自体 -> capacitor-app-upgrade-v8-to-v9 / capacitor-plugin-upgrade-v8-to-v9
  • ディープリンクを一から設定する場合 -> capacitor-deep-linking
  • Android(UIScene は iOS のみです)
  • ライフサイクルへの対応を超える、マルチウィンドウやサイズ変更可能なレイアウトの作業

稼働中のプロジェクトのスナップショット

!node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const s of ['dependencies','devDependencies','peerDependencies']){for(const [n,v] of Object.entries(pkg[s]||{})){if(n.startsWith('@capacitor/'))out.push(s+'.'+n+'='+v)}}const p='ios/App/App/';out.push('SceneDelegate.swift='+fs.existsSync(p+'SceneDelegate.swift'));if(fs.existsSync(p+'Info.plist'))out.push('UIApplicationSceneManifest='+fs.readFileSync(p+'Info.plist','utf8').includes('UIApplicationSceneManifest'));if(fs.existsSync(p+'AppDelegate.swift'))out.push('configurationForConnecting='+fs.readFileSync(p+'AppDelegate.swift','utf8').includes('UISceneConfiguration(name:'));console.log(out.join('\n'))"

監査の前提となる事実

  • UIApplicationSceneManifest が存在すると、iOS は次の AppDelegate メソッドを呼び出さなくなります:application(_:open:options:)、application(_:continue:restorationHandler:)、applicationDidBecomeActive、applicationWillResignActive、applicationDidEnterBackground、applicationWillEnterForeground。これらのメソッド内のコードは、警告もなく実行されなくなります。
  • AppDelegate で引き続き呼び出されるのは、didFinishLaunchingWithOptions、applicationWillTerminate、プッシュトークンの登録(didRegisterForRemoteNotificationsWithDeviceToken/didFailToRegister...)、リモート通知の配信です。UIApplication.*Notification のライフサイクル通知は引き続き発生します。
  • SceneDelegateProxy(CAPSceneDelegateProxy.swift)は、.capacitorOpenURL、.capacitorOpenUniversalLink(同じペイロード)、および CDVPluginHandleOpenURL を再通知し、URL を ApplicationDelegateProxy.shared.lastURL にも反映します。コールドスタート時の URL とユーザーアクティビティは、最初の .capacitorViewDidAppear まで保持されるため、プラグインは登録後にそれらを受け取り、App.getLaunchUrl() も動作します。
  • 8.5 でのみ追加された通知:.capacitorSceneWillConnect、.capacitorSceneOpenURL、.capacitorSceneOpenUniversalLink(object = UIScene、ペイロードは userInfo 内)。8.4 では通知されません。
  • JS の pause/resume は、ブリッジのシーンに絞り込んだ UIScene.didEnterBackgroundNotification/willEnterForegroundNotification によって発火します。
  • 8.5 で削除されたもの:TmpViewController、CapacitorBridge.tmpWindow、tmpViewControllerAppeared。これらを参照するとビルドエラーになります。bridge.viewController から表示してください。
  • 8.5 の SceneDelegate は、コード内でウィンドウと CAPBridgeViewController() を作成します。Main.storyboard で設定したカスタムブリッジサブクラスは、代わりに SceneDelegate でインスタンス化する必要があります。
  • cap migrate(CLI 8.5 以降)は、次の 3 つの要素でプロジェクトを分類します:Info.plist 内のマニフェスト、ディスク上の SceneDelegate.swift、AppDelegate.swift 内の UISceneConfiguration(name:。0/3 の場合は移行し、3/3 の場合は完了済みとしてスキップし、1~2/3 の場合は「部分的な状態」と警告して何もしません。既存の SceneDelegate.swift を上書きすることはありません。UIApplication.shared.applicationState、tmpWindow、TmpViewController、カスタムの open url:/continue userActivity: 本体については警告しますが、修正はしません。

手順

監査し、報告し、確認してから編集します。ユーザーに調査結果を提示する前に、編集してはいけません。

  1. リポジトリの種類を判定します。 ios/App/App.xcodeproj があればアプリです。Package.swift / *.podspec があり、CAPPlugin のソースを含み、アプリプロジェクトがなければプラグインです。手順 9 に進みます。
  2. バージョンとパッケージマネージャーを確認します。 @capacitor/ios は ^8.5.0 以上である必要があります。ios/App/Podfile があれば CocoaPods、ios/App/CapApp-SPM があれば SPM です。SceneDelegate はどちらでも同一です。
  3. スナップショットの 3 つのシグナル(対象 / 移行済み / 一部移行済み)で分類します。
  4. references/audit-patterns.md のコマンドを使用して監査し、ios/App と node_modules 内のインストール済みプラグインを確認します。見つかった項目ごとにファイル名と行番号を記録します。
  5. 次のように分類して報告します。ビルドを妨げる項目(tmpWindow、TmpViewController)、判断が必要な項目(カスタム URL / アクティビティ / ライフサイクルの処理、既存の SceneDelegate、ストーリーボードのカスタムクラス、サードパーティ SDK への転送)、参考情報(引き続き機能するオブザーバー、applicationState、node_modules 内の問題)。
  6. 実際に判断が必要な箇所では確認します。
    • open url: / continue userActivity: にカスタム処理がある場合:プロキシ呼び出しの横にある scene(_:openURLContexts:) / scene(_:continue:) に移すか確認します(先に処理内容を提示します)。
    • カスタムのライフサイクルコード:sceneDidBecomeActive / sceneWillResignActive / sceneDidEnterBackground / sceneWillEnterForeground、または UIApplication の通知オブザーバーに移すか確認します。
    • 役目を終えた AppDelegate の URL メソッドを削除するか、そのまま残すか確認します(残しても問題ありません)。
    • URL 転送を必要とする SDK(Facebook、Google Sign-In、OAuth リダイレクトライブラリ):ドキュメントで SceneDelegate のエントリーポイントを確認し、SceneDelegate から呼び出します。
  7. 適用します。
    • 対象でテンプレートに沿った構成の場合:npm i @capacitor/core@^8.5.0 @capacitor/ios@^8.5.0、npm i -D @capacitor/cli@^8.5.0 の順に実行し、その後 npx cap migrate を実行します。ログの全行を確認し、スキップされた項目はその手順に限って手動で処理します。その後、手順 6 の判断内容を適用します。
    • 一部移行済み、またはカスタマイズ済みの場合:references/scene-delegate-template.md を使用して、不足している部分だけを統合します。既存のキー、メソッド、カスタムロジックは維持します。references/pbxproj-registration.md に従って新しいファイルを登録します。
  8. 同期してビルドします。 npx cap sync ios を実行し、その後ビルドします(「検証」を参照)。3 つのシグナルを再確認し、すべてが true であることを確認します。
  9. プラグインリポジトリの場合: references/plugin-audit.md を使用して監査と助言のみを行います。プラグインリポジトリからアプリのファイルを変更してはいけません。ユーザーから依頼された場合に限り、プラグインのソースを編集します。

検証

npx cap sync ios
xcodebuild -project ios/App/App.xcodeproj -scheme App -configuration Debug \
  -destination 'generic/platform=iOS Simulator' build   # use -workspace App.xcworkspace for CocoaPods
grep -rn --include=*.swift -E '\btmpWindow\b|\bTmpViewController\b' ios/App   # expect nothing

デバイスまたはシミュレーターで確認します。

  • アプリが Web ビューを表示して起動する(黒い画面にならない)。
  • バックグラウンドからフォアグラウンドに戻したとき、JS の pause と resume がそれぞれ 1 回ずつ発生する。
  • カスタムスキームでの起動時(アプリ実行中):appUrlOpen が発生する。xcrun simctl openurl booted myscheme://test を使用します。
  • カスタムスキームでの起動時(アプリ終了後にリンクを開く):appUrlOpen が発生し、App.getLaunchUrl() が URL を返す。
  • アプリに関連付けられたドメインがある場合、ユニバーサルリンクがアプリにルーティングされる(実際のドメインと AASA ファイルが必要)。
  • プッシュ通知:トークンが引き続き届き(registration イベント)、タップした通知からアプリが開く。
  • 移動したカスタムロジック(フォアグラウンド復帰時の分析、SDK の URL ハンドラー)が実行される。

エラー処理

  • cap migrate が「partial state」と表示する -> 手作業で編集されたプロジェクトでは想定どおりです。手順 7 に従って手動でマージしてください。確認せずにファイルをリセットしないでください。
  • 移行後に画面が真っ黒になる -> SceneDelegate がウィンドウを作成していないか、Info.plist の UISceneDelegateClassName がクラスと一致していません。$(PRODUCT_MODULE_NAME).SceneDelegate とテンプレートのウィンドウ設定を使用してください。
  • AppDelegate で Cannot find 'SceneDelegate' in scope が表示される -> ファイルが App ターゲットに含まれていません。references/pbxproj-registration.md を参照してください。
  • Value of type 'CapacitorBridge' has no member 'tmpWindow' が表示される -> その参照を削除し、bridge?.viewController から表示してください。
  • ディープリンクがアプリ起動中は機能するが、起動時には機能しない -> URL の処理がまだ AppDelegate にあるか、ブリッジが表示される前にアプリが URL を読み取っています。appUrlOpen と getLaunchUrl() を使用してください。
  • カスタムブリッジのサブクラスが使用されない(capacitorDidLoad で登録されたプラグインが見つからない) -> scene(_:willConnectTo:) でサブクラスをインスタンス化してください。
  • pbxproj を手動編集した結果、Xcode でプロジェクトを開けなくなる -> 変更を元に戻し、Xcode からファイルを追加してください。

参考資料

トピックが該当する場合にのみ、参考資料を読み込んでください。

ファイル読み込むタイミング
references/audit-patterns.md手順 4:grep コマンドと各ヒットの分類方法
references/scene-delegate-template.mdSceneDelegate の作成またはマージ、Info.plist のマニフェスト、AppDelegate のフック、カスタムサブクラス、ライフサイクルの各パターン
references/pbxproj-registration.mdXcode を使わずに SceneDelegate.swift を登録する場合、または CLI で登録されたことを確認する場合
references/plugin-audit.mdリポジトリがプラグインの場合、またはインストール済みプラグインでライフサイクルに関するヒットが見つかった場合

関連スキル:capacitor-app-upgrade-v8-to-v9、capacitor-plugin-upgrade-v8-to-v9、capacitor-app-upgrades、capacitor-deep-linking、capacitor-push-notifications。

コメント