Xamarin.iOS「altool exited with code 1」対処大全:App Iconのアルファ除去とLink Allでのバイナリ最適化、Xcode Organizer/Transporterによる可視化でApp Store提出を確実に通す方法

Visual Studio 2019 でビルドした Xamarin.iOS アプリを App Store に提出しようとしたとき、「altool exited with code 1」だけが出て止まる――そんな“情報が見えない失敗”を手早く解体・修復するための実践ガイドです。Xcode Organizer/Transporter でエラーを可視化し、App Icon のアルファ除去、Linker の調整、バイナリ肥大化の抑制、ランチ画像消失の副作用対策、ビルド番号の衝突回避までを、再現性のある手順とチェックリストでまとめます。

目次

Xamarin.iOS 申請トラブルの全体像と最短ルート

本記事で扱うのは、Visual Studio 2019(Windows または Mac)で作成した Xamarin.iOS アプリを App Store Connect へアップロードする際に遭遇しやすい以下の事象です。

  • アップロード時に “altool exited with code 1” だけが表示され、詳細が何も分からない。
  • Xcode の Organizer → Archives で再検証すると、次の具体エラーが出る。
    • App Icon にアルファチャンネルが含まれている
    • armv7 用バイナリサイズが 60 MB 超
    • arm64 用バイナリサイズが 60 MB 超
  • さらに Linker 設定(Link All 推奨)を変えた結果、シミュレータでランチスクリーン画像が消える 副作用が発生。

結論から言えば、エラーの可視化 → アイコンの修正 → リンク最適化 → リソース確認 → バージョン更新 の順で対処すると、短時間で解決できます。以下で一つずつ深掘りします。

なぜ「altool exited with code 1」しか出ないのか(可視化の第一歩)

altool は検証やアップロードの詳細を標準エラー出力へ返すため、Visual Studio から直接叩いた場合は 要点が見えない ことがよくあります。最初にやるべきは エラーの可視化 です。

  • Xcode → Window → Organizer → Archives を開き、対象アーカイブを選んで Validate App または Distribute App を実行し、Xcode の UI で 具体的なメッセージを確認します。
  • もしくは Transporter.app(App Store 公式のアップロードツール)に .ipa をドラッグ&ドロップして検証・送信します。UI で失敗理由が明示され、ログも残ります。
  • CLI が必要な場合は次のようにバリデーションします(XML で詳細取得)。 xcrun altool --validate-app -f MyApp.ipa -u <Apple ID> -p <アプリ用パスワード> --output-format xml

この「見える化」を通すと、多くの場合は アイコンの透明度 や バイナリ肥大 といった具体エラーに分解できます。

エラー別:原因・確認ポイント・解決策

発生事象原因・確認ポイント解決策
「altool exited with code 1」だけ詳細は標準エラー出力へ。VS の UI からは省略されがちTransporter または Xcode → Organizer → Archives で再検証し、実際のエラー内容 を取得する
App Icon にアルファチャンネルiOS の App Icon は 完全不透明(α=1.0)が必須。透過 PNG は不可画像編集ツールで アルファチャンネルを削除して再保存。Asset Catalog の AppIcon セットを作り直し、全サイズを不透明に統一
バイナリサイズ > 60 MB(armv7/arm64)不要コード/リソースがリンクされ、アプリ Slice が肥大Linker Behavior = Link All に設定。Enable LLVM、Strip native debugging symbols、Optimize PNG files も有効化。不要アーキテクチャ削減(例:ARM64 のみに統一)
Link All でランチ画像が消えるAssets 内の Images セット の欠落、または Storyboard の参照名不一致Asset Catalog で該当 Images セットを復元 し、LaunchScreen.storyboard の「Image Name」と名称を一致させる。ビルドアクションも確認
Build Version(CFBundleVersion)衝突同一バージョンのビルドが App Store Connect に既存info.plist の Build(CFBundleVersion)をインクリメント。例:1 → 2。Short Version と区別する

App Icon を完全不透明にする:作業の要点

App Icon の透明度エラーは最も多い落とし穴です。ポイントは「全サイズを不透明 PNG でそろえる」こと。1枚でも透明を含むと失敗します。

  • 画像の用意:1024×1024 をマスターにし、縮小して各サイズ(20〜1024)を作成。透明レイヤーは削除。
  • Asset Catalog:AppIcon の各スロットをすべて埋め、欠けを残さない。
  • 保存形式:PNG で OK。ただし 透明=不可。必要なら白や黒の背景合成で不透明化。
  • 自動生成の落とし穴:一括エクスポート時に一部が透明のまま残ることがあります。ランダムに 2〜3 枚をサンプリング確認を。

コマンドラインで不透明化を自動処理したい場合は、画像処理ツールで「アルファ削除+白合成」を一括化するとヒューマンエラーを減らせます。

バイナリ肥大:Linker とアーキテクチャの最適化

armv7/arm64 の Slice サイズが 60 MB を超える場合、Linker と アーキテクチャ の見直しが最短です。

Release ビルド設定(推奨の基本形)

  • Linker Behavior:Link All(= Full)。SDK だけでなく自分のアセンブリもリンク対象にし、未参照コードを除去。
  • Supported architectures:ARM64 のみ(古い端末を切り捨て可であれば)。armv7 を外すと Slice が 1 つ減り、トータルが大幅に縮む。
  • Enable LLVM:有効。ネイティブ最適化で数%〜十数%の削減が見込めます。
  • Strip native debugging symbols:有効。シンボルをストリップして IPA を軽量化。
  • Optimize PNG files:有効。アセットの圧縮率を上げる。
  • registrar: static:動的レジストラを避けてフットプリントを縮小(Extra Args で指定)。
  • Bitcode:古いテンプレートで残っていれば無効化を検討(現在の iOS では不要)。

Linker の副作用を安全に抑える(必須の知恵)

Link All は強力ですが、リフレクションや XAML/Storyboard 経由で暗黙参照している型・メンバーを「未使用」と誤判定しがちです。対策は次の 3 本柱です。

  1. [Preserve] 属性で保護 using Foundation; [Preserve(AllMembers = true)] public class MyViewModel { // … }
  2. LinkerPleaseInclude.cs を用意(アクセスだけするダミーコードで参照を生やす) public class LinkerPleaseInclude { public void Include(UIKit.UIImageView v) { v.Image = v.Image; } }
  3. –linkskip で特定アセンブリをリンク対象から外す(最終手段) // iOS Build → Additional mtouch arguments --linkskip=Newtonsoft.Json

グローバリゼーション(i18n)を絞る

.NET のグローバリゼーション関連アセンブリはサイズ増の一因です。Extra Args の --i18n で必要なセットだけに絞ります。

  • 日本語を含むなら --i18n=cjk を選択(west だけにすると日本語処理が欠けます)。
  • 複数をカンマで併記可能(例:--i18n=cjk,mid)。

不要アーキテクチャを外す判断軸

  • サポート OS バージョン を iOS 11 以降に設定できるなら、ARM64 のみで十分なケースが多い。
  • 古い端末をサポートする場合は armv7 を残しますが、容量制約にかかるなら、機能削減か配布対象の見直しを検討。

Link All にしたらランチスクリーンが消えた:原因の切り分け

Linker が画像を「未参照」と誤って除外したというよりも、Asset Catalog の Images セット欠落や名称不一致が原因であることがほとんどです。次の順で確認します。

  1. Assets.xcassets 内に、LaunchScreen.storyboard が参照する Image Set(例:LaunchImage)が存在するか。
  2. Storyboard の Image View → Image に設定された名称が、Image Set と完全一致しているか(大文字小文字も含む)。
  3. Image Set の各スロット(1x/2x/3x)が埋まり、ビルドアクションが BundleResource になっているか。
  4. 「Optimize PNG files」有効時にも問題なく表示されるか(最終確認として実機でチェック)。

上記を満たせば、Link All のままでもランチ画像は正常に表示されます。Assets から画像セットを誤って削除していた場合は、該当セットを復元すれば解決です。

ビルド番号の衝突(CFBundleVersion)を防ぐ運用

App Store Connect には同一 Short Version に対して、ビルド番号(CFBundleVersion)が単調増加 という制約があります。解決は単純で、info.plist のビルド番号をインクリメントするだけです。衝突を恒久的に避けるなら、CI で自動採番するのが有効です。

// 例:日付+通番
CFBundleShortVersionString = 1.4.0
CFBundleVersion           = 2024110201

チームで手動更新する場合は、ビルド前フックで PlistBuddy を使って書き換えるとミスが減ります。

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion 2024110201" path/to/Info.plist

具体手順:Visual Studio 2019(Windows)+ Mac ビルドホスト

  1. Release|iPhone 構成に切り替え。
  2. iOS Bundle Signing:Distribution 証明書と App Store 用プロビジョニングを選択。
  3. iOS Build:
    • Linker Behavior:Link All
    • Supported architectures:ARM64(可能なら単独)
    • Enable LLVM:On
    • Strip native debugging symbols:On
    • Optimize PNG files:On
    • Additional mtouch arguments: --registrar:static --i18n=cjk
  4. ビルド番号 を更新(info.plist)。
  5. Archive を作成(メニューの アーカイブ)。
  6. .ipa のエクスポート(Distribute → App Store → Upload または Export)。
  7. Xcode → Organizer → Archives で対象アーカイブを選び Validate。問題なければ Distribute。
  8. あるいは Transporter に .ipa をドラッグし、検証 → 送信。

csproj による再現性ある設定(サンプル)

GUI 設定は便利ですが、差分が見えづらいのが難点です。再現性と運用性を上げるため、Release|iPhone の条件付きで csproj に明示することを推奨します。

&lt;PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|iPhone'"&gt;
  &lt;MtouchLink&gt;Full&lt;/MtouchLink&gt;            &lt;!-- Link All --&gt;
  &lt;MtouchArch&gt;ARM64&lt;/MtouchArch&gt;             &lt;!-- armv7 を外し容量削減 --&gt;
  &lt;MtouchUseLlvm&gt;true&lt;/MtouchUseLlvm&gt;
  &lt;MtouchExtraArgs&gt;--registrar:static --i18n=cjk&lt;/MtouchExtraArgs&gt;
  &lt;CodesignEntitlements&gt;Entitlements.plist&lt;/CodesignEntitlements&gt;
&lt;/PropertyGroup&gt;

一部のライブラリでリンク除外が必要なら、MtouchExtraArgs へ --linkskip=AssemblyName を追加し、最小限で運用します。

サイズ最適化をもう一段攻めるテクニック

  • 画像アセットの見直し:未使用の @3x/@2x を削除。SVG→PDF(ベクタ)対応のアセットは PDF ベースに切り替え。
  • リソースの遅延ロード:初回起動サイズの圧迫を避け、後段でダウンロードする(規約・審査観点と UX のバランスに配慮)。
  • 文字フォント:巨大なカスタムフォントは可変フォントやサブセット化を検討。
  • 静的レジストラ:--registrar:static を基本とし、動的レジストラ分のオーバーヘッドを削減。
  • AOT 最適化オプション:LLVM と組み合わせ、Release だけに限定適用。

検証ログを読むコツ(Xcode Organizer/Transporter)

エラーの表現はしばしば冗長です。読み解きのポイントを押さえると、原因特定が速くなります。

  • App Icon:文末に with alpha channel とあれば 100% 透明が原因。どのサイズかも記載されることが多い。
  • Binary Size:armv7 slice > 60 MB のように Slice 別の閾値に触れる。armv7 を外す/Link All 化で改善する。
  • Version:CFBundleVersion must be higher と明示。ビルド番号のみ上げればよい。

よくある質問(実務でつまずくポイント)

Q. Link All にすると起動時クラッシュします。

[Preserve] と LinkerPleaseInclude を追加し、反射解決している ViewModel/カスタムレンダラ/JSON バインディング対象などを保護してください。改善しない場合、問題のライブラリだけ --linkskip=LibName でリンク除外し、影響範囲を最小化します。

Q. 画像は消えないのに、特定の XAML(または Storyboard)の要素が出ません。

動的に Type.GetType() などで解決している場合、型がリンクで落ちている可能性があります。該当クラスに [Preserve(AllMembers=true)] を付けるか、LinkerPleaseInclude で明示的に参照を生やしてください。

Q. どうしても 60 MB の閾値を割れません。

  • armv7 を外せるか検討(サポート OS と端末要件を見直す)。
  • 大容量のネイティブ SDK(例:ML/AR 系)を使っている場合、静的リンクの代替や必要機能の最小セット化を検討。
  • リソースの外部配信(初回は軽量、必要に応じてダウンロード)へ設計変更。

Q. Visual Studio 側では成功するのに、審査で弾かれます。

最終検証は Xcode Organizer での Validate を正とし、Transporter のログまで確認する運用を推奨します。VS の出力はサマリであり、詳細は省略されがちです。

チェックリスト:提出直前の 60 秒点検

  • App Icon:全サイズが不透明。透明を含む PNG は 0 件。
  • Asset Catalog:Launch 用 Image Set が存在し、Storyboard の Image 名称 と一致。
  • iOS Build:Link All/ARM64/Enable LLVM/Strip Symbols/Optimize PNG を有効。
  • mtouch:--registrar:static、必要に応じて --i18n=cjk。
  • ビルド番号:CFBundleVersion をインクリメント。Short Version は据え置きで OK。
  • Xcode Organizer:Validate → Distribute の順で問題なし。

トラブル再現〜解消の“手順書”テンプレート

チームで共有できるよう、以下のテンプレートをそのまま社内 Wiki に貼り付けて使えます。

【前提】
- VS2019 / Xamarin.iOS
- iOS Provisioning: Distribution
- Build: Release|iPhone

【手順】

1. info.plist の CFBundleVersion を +1
2. iOS Build 設定を確認

   * Linker Behavior = Link All
   * Supported architectures = ARM64
   * Enable LLVM = On
   * Strip native debugging symbols = On
   * Optimize PNG files = On
   * Additional mtouch args = "--registrar:static --i18n=cjk"
3. Assets.xcassets を開き、AppIcon 全サイズが不透明であることを目視確認
4. LaunchScreen.storyboard の Image 名と Asset の Image Set 名を一致
5. Archive → Export .ipa
6. Xcode → Organizer → Archives → Validate → Distribute
7. エラーがあればメッセージを基に該当項目を修正 

トラブルの背景(仕組みから理解する)

なぜ App Icon の透明がダメなのか? iOS のホーム画面での描画最適化・統一感確保のため、角丸や影などの装飾は OS が担い、アイコン画像側は「完全不透明の四角」で提供する前提になっています。透明ピクセルが混じるとアップロード段階で検証に失敗します。

なぜ Link All がサイズ削減に効くのか? Xamarin.iOS は AOT で .NET アセンブリをネイティブ化しますが、未参照コードも含めたままだとネイティブ側に変換され、バイナリを押し上げます。Link All は「リフレクションでの暗黙参照」などを除き、未使用の IL を大胆に間引くため、Slice サイズが大きく下がります。副作用は [Preserve] や LinkerPleaseInclude でコントロール可能です。

デバッグに効く小ネタ集

  • IPA を解凍して中を確認:Payload/<AppName>.app 配下に巨大な Framework や不要リソースがないかを直接チェック。
  • シミュレータと実機を分けて確認:シミュレータは x64/ARM64 Mac 向け Slice で動作条件が異なります。App Store 申請は 実機用 Release を正として検証。
  • サイズ増加の回帰検知:CI で IPA サイズの閾値チェックを入れ、PR 時に差分をレビュー。

最終まとめ:解決への導線

「altool exited with code 1」で詰まったら、まずは Organizer/Transporter で可視化。エラーが「App Icon のアルファ」「Slice サイズ超過」「ビルド番号の衝突」であれば、

  1. App Icon を完全不透明で作り直し、Asset Catalog を更新。
  2. iOS Build を Link All+ARM64+LLVM+Strip Symbols+Optimize PNG へ最適化。必要なら --i18n 調整。
  3. ランチ画像は Assets の Image Set 復元 と名称一致で解消。
  4. CFBundleVersion を +1 して再アーカイブ。
  5. Xcode Organizer で Validate → Distribute を通す。

この順番で実施すれば、再現性高くエラーを潰し込み、App Store への提出を完了できます。チームでは csproj へ設定を明記し、テンプレート手順とチェックリストを運用することで、次回以降の工数を最小化できます。

付録:実際に使える比較表(再掲・拡張)

項目推奨設定補足・副作用
Linker BehaviorLink All未参照コードを徹底削減。反射利用は [Preserve] で保護
Supported architecturesARM64(可能なら単独)古い端末切り捨てとトレードオフ。容量インパクト大
Enable LLVMOnサイズ・性能が改善。ビルド時間はやや増
Strip native debugging symbolsOnデバッグ時は dSYM を別途収集
Optimize PNG filesOn見た目は変えず容量を圧縮
registrarstatic動的レジストラ分のオーバーヘッド削減
i18ncjk日本語環境を想定。west 単独は避ける
CFBundleVersion単調増加Short Version と混同しない
App Icon完全不透明 PNG透明ピクセルが 1 つでもあれば失敗

付録:よく使う mtouch 引数メモ

// 反射保護は [Preserve] と LinkerPleaseInclude が基本。必要時のみ:
--linkskip=AssemblyName       // 特定アセンブリをリンク除外
--registrar:static            // 静的レジストラを使用
--i18n=cjk                    // 日本語を含むグローバリゼーションをロード
--optimize=all                // 追加最適化(環境により効果差あり)

これで提出できる:最終フローのひな形

  1. 設定見直し(Linker/Arch/i18n/PNG など)→ Archive。
  2. Xcode Organizer で Validate → NG なら該当箇所をピンポイント修正。
  3. Transporter または Organizer で Distribute。
  4. App Store Connect 側でビルド選択 → 審査提出。

同じミスを繰り返さないために、この記事のチェックリストと csproj スニペットをそのままプロジェクトに取り込み、“ビルドすれば通る” 再現性を担保してください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次