.NET MAUI を .NET 9 に上げた途端、MacCatalyst ビルドで「MacCatalyst 18.2 SDK(Xcode 16.2)が必要」と怒られて止まる…。Xcode を入れ直しても 15.4 のまま、さらに OS 更新後は VS Code のデバッグだけ動かない。そんな詰まりポイントを、原因の考え方から最短で直す手順までまとめます。
発生するエラーと状況
.NET MAUI アプリを .NET 8 → .NET 9 にアップグレードした直後、MacCatalyst ターゲットのビルドで次のようなエラーが出て停止することがあります。
This version of Microsoft.MacCatalyst requires the MacCatalyst 18.2 SDK (shipped with Xcode 16.2).
やっかいなのは、Xcode を入れ直しても Xcode 15.4 のままで、要求されている Xcode 16.2(= MacCatalyst 18.2 SDK 同梱)にならないケースがあることです。今回の前提は次のとおりです。
| 項目 | 状況(例) | 補足 |
|---|---|---|
| .NET | .NET 9(MAUI)へ更新 | workload 更新は成功している前提 |
| macOS | Sonoma 14.4.1 | ここがボトルネックになりやすい |
| Xcode | 15.4 から上がらない | 再インストールしても同じ |
| 追加で起きた問題 | OS/Xcode 更新後、CLI ビルドは成功するが VS Code のデバッグだけ失敗 | 後半で対処を解説 |
原因:.NET 9 側の「Apple SDK 前提」が上がった
このエラーの本質は、.NET 9 の MAUI(正確には Microsoft.MacCatalyst ワークロード)が要求する Apple 側 SDK と、ローカルに入っている Xcode の SDK が一致していないことです。
MAUI の MacCatalyst ビルドは内部で Xcode のツールチェーン(xcodebuild / clang / codesign 等)と、Xcode に同梱される各種 SDK を参照します。つまり、dotnet の更新だけ進めても Mac 側の Xcode/SDK が追いついていないと、ビルド前提チェックで止まります。
「Xcode を入れ直しても 15.4 のまま」になる理由
ここでハマりどころになるのが、App Store の挙動です。App Store は基本的に「その macOS で動作可能な範囲の Xcode」しか提示しません。macOS が古いままだと、最新の Xcode が検索に出てこない/更新ボタンが出ない/入れ直しても同じ版になる、という現象が起こります。
今回のケースでは、Xcode 16.2 を入れたくても、macOS Sonoma 14.4.1 のままだと条件を満たせず、結果として 15.4 に張り付いてしまう、という構図です。
結論:Xcode 16.2 と、それが動く macOS バージョンに揃える
最短の解決はシンプルで、OS(macOS)→ Xcode → 選択中の Xcode パスの順に整えます。今回の解決方針を表にまとめると次のとおりです。
| やること | 目的 | この順番にする理由 |
|---|---|---|
| macOS を更新(Sonoma 14.5 以降) | Xcode 16.2 をインストール可能にする | OS が古いと App Store 側で Xcode が出ない |
| Xcode 16.2 をインストール | MacCatalyst 18.2 SDK を揃える | .NET 9 側の要求と一致させる |
| xcode-select で Xcode を切り替え | dotnet が参照する Xcode を確定 | 複数 Xcode があると古い方を見て失敗しがち |
| 必要な場合のみ workload を確認・更新 | MAUI 側の不整合を解消 | 基本は Xcode が揃えば再インストール不要 |
まずは現状確認:どこが古いのかを“数字で”押さえる
環境依存のトラブルは「体感」より「コマンド結果」が早いです。ターミナルで次を実行して、今のバージョンと参照先を確認します。
macOS の確認
sw_vers
Xcode の確認(バージョンとパス)
xcodebuild -version
xcode-select -p
dotnet / workload の確認
dotnet --info
dotnet workload list
ここで重要なのは、Xcode の「インストール済み」と「選択されている」が別物になり得る点です。Xcode を 2 本以上置いている場合、古い Xcode を参照していてエラーが出続けることがあります。
解決手順:macOS を更新して Xcode 16.2 を入れる
macOS を Sonoma 14.5 以降へ更新する
まず OS を更新します。Sonoma のマイナーアップデート(例:14.7.2 など)であれば、通常は個人データやアプリが消えることはありませんが、アップデートは何が起きてもおかしくない作業なので、心配ならバックアップを取ってから進めるのが安全です。
- Time Machine を使えるなら最優先で実行
- 開発中のリポジトリは Git に push / 別ディスクへ退避
- 容量不足でアップデートが詰まることがあるので空き容量も確認
更新後は再起動が入るため、アップデートが完了したら sw_vers でもう一度 macOS のバージョンを確認します。
Xcode 16.2 をインストールする
OS を更新したら、App Store から Xcode 16.2 をインストールします。Xcode が複数存在すると後々のトラブル要因になるので、古い Xcode を残す場合も「どれを参照しているか」を明確にできる配置にするのがおすすめです。
- シンプルにするなら旧 Xcode を削除(/Applications/Xcode.app を入れ替え)
- 残すなら
/Applications/Xcode_15.4.appのようにリネームして並置
xcode-select で参照先を確定し、初回セットアップを済ませる
Xcode のインストール直後は、ライセンス承諾や追加コンポーネントの初期化が未完了で、ビルドやデバッグが不安定になることがあります。次の 3 点はセットで実施してください。
# 参照する Xcode を明示(Xcode が複数ある場合は特に重要)
sudo xcode-select -s /Applications/Xcode.app
# ライセンス承諾(表示される場合)
sudo xcodebuild -license accept
# 初回セットアップ(必要に応じて)
sudo xcodebuild -runFirstLaunch
最後に、SDK の一覧を表示して、想定どおり新しい SDK 群が認識されているか確認します。
xcodebuild -showsdks
MAUI workload は“基本的に”入れ直し不要
今回のように「.NET 側のアップグレードと workload 更新がすでに通っている」なら、OS 更新後に MAUI ワークロードを丸ごと入れ直す必要はほとんどありません。まずはそのままビルドしてみて、まだ詰まる場合だけ、次を検討します。
- プロジェクトの依存を再解決したい:
dotnet workload restore - workload を最新に揃えたい:
dotnet workload update - 壊れた状態を疑う:
dotnet workload repair
dotnet workload restore
dotnet build -f net9.0-maccatalyst
それでもビルドできない場合のチェックポイント
OS と Xcode を揃えたのに同じエラーが出るときは、「参照している Xcode が違う」「キャッシュが古い」「パスや権限が壊れている」などの可能性が高いです。よく効くチェックを表にまとめます。
| 症状 | 原因の候補 | 確認・対処 |
|---|---|---|
| インストール済みは 16.2 のはずなのに、ビルドログでは古い SDK を見ている | xcode-select が旧 Xcode を指している | xcode-select -p を確認し、sudo xcode-select -s で切り替え |
| Xcode だけ入れたが、初回起動していない | ライセンス/追加コンポーネント未完了 | Xcode を一度起動し、sudo xcodebuild -license accept を実行 |
| CLI でも SDK 関連で落ちる | Command Line Tools の参照がずれている | xcode-select -p が /Applications/Xcode.app になっているか確認 |
| ビルドは通るが実行時に落ちる/リンクが怪しい | キャッシュや古い obj/bin が残っている | dotnet clean の後に bin/obj を削除して再ビルド |
クリーンビルドの手順(安全な範囲)
プロジェクト直下の生成物を消してやり直すだけでも改善することがあります。最初はこの程度から試すのが安全です。
dotnet clean
rm -rf bin obj
dotnet build -f net9.0-maccatalyst
追加問題:CLI ビルドは成功するのに VS Code のデバッグだけ動かない
OS と Xcode を正しく揃えた後でも、VS Code からのデバッグだけが起動しない(ターミナルからのビルドは成功する)というケースがあります。これは「dotnet のビルド環境」と「VS Code の拡張機能・デバッグアダプタ」が別レイヤーだからです。
| できること | 状態 | 示唆 |
|---|---|---|
ターミナルで dotnet build | 成功 | Xcode/SDK と dotnet の組み合わせは概ね OK |
| VS Code の「実行とデバッグ」 | 失敗 | 拡張機能・デバッグ設定・VS Code 側キャッシュの問題を疑う |
まず疑うべきポイント
- VS Code 本体や拡張機能が OS 更新後に不整合を起こしている(特に C# 系拡張)
- VS Code が見ている dotnet のパスがターミナルと違う(brew 版と公式版が混在など)
- Gatekeeper / 権限の影響でデバッガ関連バイナリがブロックされている
- ワークスペース側の
.vscode/launch.jsonやtasks.jsonが古い前提のまま
効果が高い対処:VS Code を再インストールする
今回のケースでは、VS Code をアンインストール → 再インストールし、拡張機能と関連パッケージを更新したところ解消しています。VS Code は設定や拡張のキャッシュが広範囲に散らばるため、アップデートの繰り返しで状態が崩れると、再インストールが最短になることが珍しくありません。
再インストール前にやっておくと安心なこと:
- 設定同期を使っているなら、同期が完了しているか確認
- 重要なワークスペース設定(
.vscode配下)は Git 管理しておく - 拡張機能の一覧をメモ(後で入れ直しやすくする)
「VS Code が見ている dotnet」が違う問題を潰す
ターミナルでは動くのに VS Code のターミナル(またはデバッグ)で動かない場合、dotnet の参照先が違うことがあります。次を両方で実行して差がないか確認します。
which dotnet
dotnet --info
パスが違う場合は、brew 版を使うのか、公式インストーラ版を使うのかを決めて、片方に統一するとトラブルが減ります。
デバッグ前提の最小チェック
- Xcode を一度起動して、追加コンポーネントのインストールが終わっている
xcode-select -pが目的の Xcode を指している- シミュレータや実機を使う場合は、対象が起動できる状態になっている
- ワークスペース内で
dotnet buildが通ることを確認してからデバッグに進む
ビルドログの warning は“止血”と“改善”を分けて考える
環境が整うとビルド自体は通る一方で、ログに大量の warning が出て不安になることがあります。ただし、今回の「Xcode/SDK 不足」のようにビルドを止める致命要因と、将来の不具合を減らす改善要因は別です。優先順位を付けて対処しましょう。
Application.MainPage の非推奨警告
MAUI の進化に伴い、アプリ起動やウィンドウ生成まわりの推奨パターンが変わることがあります。非推奨警告は「今すぐ壊れる」ではなく「次の移行で困る」サインなので、ビルドが安定した後に、該当箇所を新しい推奨 API へ寄せていくのが現実的です。
null 参照関連の警告
C# の null 許容参照型(nullable reference types)を有効にしていると、移行時に warning が増えがちです。実害が出やすいのは次の 2 パターンです。
- イベントハンドラやコールバックで想定外の null が来てクラッシュする
- 非同期初期化の順序が変わり、null のまま UI が触られる
ログに出るファイルと行番号を起点に、? / ! の付け方や、初期化タイミングの整理を進めると、結果的に移行後の品質が上がります。
XamlC の最適化警告
XAML コンパイル(XamlC)関連の警告は、パフォーマンスやトリミング(不要コード削減)に影響することがあります。ビルド停止の原因にはなりにくいものの、アプリサイズや起動速度に効いてくるので、リリース前に潰す価値が高い領域です。
SkiaSharp と OpenGLES のリンク警告(MacCatalyst には OpenGLES がない)
ログに SkiaSharp.Views.iOS.dll が絡んで OpenGLES が MacCatalyst に存在しないという警告が出る場合、プロジェクトが「本来 MacCatalyst 向けではない iOS 向けアセンブリ」を参照している可能性があります。
すぐに落ちるわけではない場合もありますが、次の観点で見直すとスッキリします。
- SkiaSharp 関連パッケージが最新か(古い組み合わせだと余計な参照を引くことがある)
- MAUI 向けのパッケージ(例:Maui 向けビュー)に寄せられないか
- 本当に iOS 向けの Views を直接参照する必要があるか
今後のアップグレードで詰まらないための運用
MAUI のアップグレードで毎回ハマる場合、個別の修正だけでなく「環境の揃え方」を運用として固めるとラクになります。
環境を固定する:global.json で .NET SDK をピン留め
チーム開発や複数マシン運用では、.NET SDK を揃えておくと再現性が上がります。プロジェクト直下に global.json を置くと、意図しない SDK でビルドされる事故が減ります。
アップグレード前に“依存する外部要件”を先に確認する
MAUI は Apple 側のリリースサイクル(Xcode / SDK)にも強く影響されます。アップグレード時は、次の順に確認しておくと、今回のような「Xcode が上がらない」問題に早く気づけます。
- ターゲット OS(iOS / MacCatalyst)の要求が上がっていないか
- それに対応する Xcode が、手元の macOS で動くか
- CI やビルド用 Mac の OS を上げられるか
“ビルド用 Mac”と“普段使い Mac”を分けるのも有効
どうしても業務都合で普段の Mac をすぐ最新にできない場合、ビルド・署名だけを担当する Mac(または CI)を別に用意し、そちらだけ Xcode と macOS を追従させる運用も現実的です。MacCatalyst を含む Apple 向けビルドは、結局「最新の Xcode が動く macOS」が必要になりやすいからです。
よくある質問
OS を更新したらデータは消えますか?
通常の macOS アップデートでユーザーデータが消えることは基本ありません。ただし、アップデートの失敗やディスク障害のリスクはゼロではないため、重要データはバックアップを推奨します。
MAUI workload は本当に入れ直さなくていいですか?
先に workload 更新が成功しており、Xcode と macOS を揃えたあとにビルドが通るなら、入れ直しは不要なことが多いです。もしまだ不整合が疑われる場合だけ、dotnet workload restore/update/repair を段階的に試してください。
どうしても macOS を上げられない場合は?
手元の Mac を更新できない場合、現実的な回避策は次のいずれかです。
- .NET 8 のまま維持して、要求される Xcode/SDK の水準が上がるタイミングを遅らせる
- 別の Mac(または CI)に macOS と Xcode を揃えて、そこでビルドする
いずれにせよ「.NET 側が要求する SDK」と「Xcode が提供する SDK」を一致させる必要がある点は変わりません。

コメント