WindowsだけでiOSアプリを出す方法と、実際に踏んだ7つの罠|Intel Macが詰んだ話
手元にMacはあった。Intelだった。
iPhoneアプリを作ろうと思ったとき、最初に確認したのは「Macがあるか」でした。
ありました。MacBookがしかもMacbookPro。

これで勝ったと思ったんですが、そんなに甘くはなかった。そのMacはIntel製で、macOS Ventura以降のアップデートに対応していなかったのです。
「まあOSが古いだけでしょ」と思うじゃないですか。思いますよね。私も思いました。でもここから、なかなかよくできた三段構えの罠が始まります。
AppleはXcodeが動くmacOSのバージョンを縛っている。 新しいXcodeは新しいmacOSでしか動かない
macOSが上がらなければXcodeも上がらない。 Intel機はある世代でアップデートが打ち切られる
App Storeは古いXcode・古いiOS SDKでビルドしたアプリを受け付けない。 提出時点で弾かれる
きれいに詰んでいます。パズルゲームなら良問と言われるやつです。
つまり「Macを持っている」では条件を満たしません。「現行のXcodeが動くMacを持っている」でなければ意味がない。ここが最初の学びでした。
Macは買い物ではなく、サブスクだった
ここで普通は「じゃあ新しいMac買うか」となります。私も一瞬なりました。
でも冷静に考えると、買ったところで数年後にまったく同じ壁が来ます。今度はApple Silicon機が切られる番になるだけで、構造は何も変わりません。
つまりiOS開発におけるMacは、一度買えば終わりの機材ではなく、Appleの都合で数年ごとに更新を要求される定期費用なんですね。気づいたときはちょっと遠い目になりました。
そこで方針を変えました。Macを買い替えるのではなく、必要なときだけクラウドのMacを借りることにしたのです。
結論: WindowsだけでiOSアプリは出せる
出ます。実際にこの構成で4本リリースしました。
先に正直に断っておくと、「Macが1台も無くていい」とまでは言えませんでした。理由は罠0で書きます。ただしビルドとリリースの工程にMacは一切使っていません。
Windowsで開発 → GitHubにpush → Codemagicがクラウド上のMacでビルド
→ TestFlightへ自動アップロード → iPhone実機でテスト → App Store審査へ提出
証明書もプロビジョニングプロファイルも、Apple Developerのサイトとブラウザだけで作れます。
必要なものは以下だけです。
Apple Developer Program(年間 $99。これは避けられません)
Codemagic(個人開発の規模なら無料枠で足ります)
GitHubのリポジトリ(プライベートでOK)
iPhone実機(これだけは代替不可。理由は下記)
銀行口座と税務情報の登録(アプリ内課金を入れるなら必須。詳細は罠0)
実機について補足しておくと、Macが無いということはiOSシミュレータも無いということです。Xcodeが無いのだからシミュレータもありません。つまりiOSでの確認手段は実機 + TestFlight の一択になります。
しかもTestFlightに載せるには署名もビルドもアップロードも全部成功している必要があるので、「ちゃんと動くか確かめる」ために先にパイプラインを全部通さないといけない。Androidなら5秒でエミュレータに出るものが、iOSでは全工程を突破するまで一切見えません。ここは手順を考えるうえで頭に入れておいてください。
逃げの選択肢のはずが、思わぬ副産物があった
クラウドビルドは消去法で選んだのですが、使ってみると利点がありました。
ビルド環境が毎回まっさらなので再現性があること。そしてmacOSやXcodeのバージョンをyamlに書いて固定できることです。
手元のMacだと「いつの間にか環境が変わっていて、昨日通ったビルドが今日通らない」が起きますが、それが構造的に起きません。これは思っていたより快適でした。
ここからが本題: 7つの罠
とはいえ、最初のビルドが通るまでは荒野でした。しかもエラーメッセージから原因が分からないものが多い。ここを共有するのがこの記事の目的です。
先に、環境の話ではない罠をひとつ書きます。これは「知らないと着手すらできない」タイプの壁です。
罠(番外編): 銀行口座の登録が、Windowsのブラウザではどうしても通らなかった
無料アプリだけを出すなら関係ありません。しかしアプリ内課金を入れた瞬間、これが必須になります。
App Store Connectには「有料App契約(Paid Applications Agreement)」というものがあり、これを締結しないとアプリ内課金の商品を販売できません。そして締結には銀行口座の登録と税務情報の提出が必要です。
厄介なのは、これがコードの問題ではないので気づくのが遅れることです。アプリは完成している。課金の実装も終わっている。なのに商品が有効にならない。
ただ、本当に困ったのはその先でした。
App Store Connectの登録画面が、Windowsのブラウザでどうやっても通らなかったのです。
入力内容を何度見直しても、ブラウザを変えても、先に進みません。エラーらしいエラーも出ない。ただ通らない。
半ば諦めかけたところで、ふと思い立って例のIntel Macで同じ操作をしました。あっさり通りました。
ビルドには古すぎて使えないと判断したMacが、まったく別の場面で唯一の解決手段になった。このときばかりは処分しなくてよかったと思いました。
なお原因は今も分かっていません。 ブラウザの違いなのか、特定のUIの問題なのか、たまたまなのか。特定できていないので、ここでは「そういうことが起きた」という事実だけ書いておきます。
そしてこれを踏まえると、この記事の結論は少しだけ変わります。
ビルドとリリースにMacは要りません。でも「Macが1台も無くていい」とは言い切れません。
Appleの管理画面には、こうした説明のつかない挙動がまだ潜んでいる可能性があります。そして次にどこで踏むかは分かりません。
なので私の今のスタンスは、型落ちでもいいのでMacを1台は持っておくです。ビルド用ではなく、いざというときの避難先として。
ちなみに口座と税務情報は、アプリを作り始めた時点で先に済ませておくのが正解です。実装が終わってから始めると、その分だけ丸ごとリリースが遅れます。
ここからは環境まわりの罠です。
罠1:「Failed to set code signing settings」の原因はUTF-8 BOMだった
Windowsでプロジェクトファイルを編集すると、エディタが親切心でBOMを付けることがあります。これが混入すると、署名処理が Failed to set code signing settings で落ちます。
このエラーメッセージ、原因をまったく示していません。私は署名周りを疑って証明書を作り直したりしました。全部無駄でした。犯人はBOMです。
検査はPowerShellでこれだけ。
$b=[IO.File]::ReadAllBytes('ios\Runner.xcodeproj\project.pbxproj')
if ($b[0] -eq 0xEF -and $b[1] -eq 0xBB -and $b[2] -eq 0xBF) { 'BOMあり' } else { 'クリーン' }罠2:「.gitignore がShift-JIS」でFlutterのビルドが落ちる(UTF-8デコードエラー)
これはWindows開発者だけが踏む、実に理不尽な罠です。
Flutter 3.44系はSwiftPMへの移行チェックのため .gitignore を読みます。そこにShift-JISの日本語コメントが入っていると、UTF-8デコードに失敗してクラッシュします。
なぜShift-JISが混入するのか。PowerShellの Set-Content / Add-Content はデフォルトの文字コードがANSI(CP932)だからです。日本語コメントを書き足した瞬間に地雷が埋まります。
対策は -Encoding utf8 を必ず付けること。そして定期的に全ファイルを検査すること。
git -c core.quotepath=false ls-files | %{ $f=$_; try { [void](New-Object Text.UTF8Encoding($false,$true)).GetString([IO.File]::ReadAllBytes("$pwd\$f")) } catch { "NG: $f" } }罠3:「The sandbox is not in sync with the Podfile.lock」はSwiftPMが原因
Flutter 3.44系はiosプロジェクトをSwiftPMへ自動移行しようとします。ところがCocoaPods構成と混在すると The sandbox is not in sync with the Podfile.lock で失敗します。
ビルドスクリプトの先頭で無効化するのが確実です。
flutter config --no-enable-swift-package-manager罠4: ビルドは成功するのにTestFlightに降りてこない(輸出コンプライアンス)
Info.plistに ITSAppUsesNonExemptEncryption を書いていないと、ビルドのたびにApp Store Connectで輸出コンプライアンスの手動回答を求められます。そして回答するまでTestFlight配信が保留されます。
「ビルドは成功しているのに端末に降りてこない」と悩む時間が発生します。通信しないアプリなら false を入れておくだけです。
<key>ITSAppUsesNonExemptEncryption</key>
<false/>罠5: アップロード検証で409エラー → UIRequiresFullScreen が無い
これが無いとアップロード検証で409エラーが返ります。iPadのマルチタスク要件によるもので、縦持ち専用のつもりでもiPadで動く扱いになるため必要です。
<key>UIRequiresFullScreen</key>
<true/>罠6: audioplayers が iOS 13.0 を要求する(Podfileの書き方)
音を鳴らすために audioplayers を入れたところ、iOS 13.0以上を要求されました。Podfileでグローバルプラットフォームと、さらに全Podのデプロイメントターゲットも揃える必要があります。片方だけだと通りません。
platform :ios, '13.0'
# post_install 内で全Podも揃える
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'おまけの罠: App Storeの「言語」欄が勝手に「EN 英語」になる
これはビルドではなくメタデータの話ですが、地味に痛いので共有します。
Info.plistに日本語宣言を入れ忘れると、App Storeの「言語」欄が「EN 英語」と表示されます。日本語のアプリなのに。
そしてこれはストア側では直せません。修正には再ビルドと再審査が必要です。1本目のアプリでやらかしました。
<key>CFBundleDevelopmentRegion</key>
<string>ja</string>
<key>CFBundleLocalizations</key>
<array>
<string>ja</string>
<string>en</string>
</array>細かいけど知らないと混乱すること
Codemagicはビルド番号を自動採番します。なので pubspec.yaml の +N の部分は上書きされ、効くのはバージョン名の方だけです。
これを知らないと「ビルド番号を上げたのに反映されない」と首をかしげることになります。私は3分ほど首をかしげました。
そして審査へ
無事にビルドが通ってTestFlightに乗り、実機で確認して、いよいよ審査提出。
……からの、2週間の沈黙。
Appleは「提出の90%は24時間以内に審査される」と公表していますが、新規アプリ+アプリ内課金ありの初回リリースは長引くことがあるようです。ステータスは「審査待ち」のまま、10日を過ぎても微動だにしませんでした。
ここで大事なのは、慌てて審査から取り下げないことです。取り下げて出し直すとキューの最後尾に戻ります。じっと待つのが正解でした。
なお2本目以降のアップデート審査は、数時間から数日で通ります。苦しいのは最初だけです。
エピローグ
その後、新しいMacを買いました。結局買うんかい、という話なんですが、3Dレンダリングなど別用途で必要になったためです。
ではビルドをそちらに戻したかというと、戻していません。今もCodemagicのままです。
理由は先に書いた副産物です。環境がyamlで固定されていて、毎回まっさらで、再現性がある。一度この快適さを知ると、手元でビルドする理由がありませんでした。
Macが無くて詰んでいる人はもちろん、Macがあっても古くて詰んでいる人、そして手元のビルド環境が壊れて途方に暮れている人にも、選択肢としておすすめします。
ただ、最後にもう一度だけ。
古いMacは捨てないでください。 ビルドには使えなくても、Appleの管理画面が突然言うことを聞かなくなったとき、それが唯一の逃げ道になることがあります。私が実際にそうでした。
「Mac不要」は半分本当で、半分は嘘です。正確には**「ビルド用のMacは要らない。でも1台は持っておいた方がいい」**。これが4本出した今の実感です。
ここまでお読みいただき、ありがとうございました。
7,000字にわたって罠の話ばかりしてしまいましたが、裏を返せば罠さえ避ければ本当に出せるということです。私が丸一日溶かしたBOMの件も、知ってさえいれば3分で終わります。
この記事のどれか一つでも、あなたが溶かすはずだった時間を減らせていれば幸いです。
もし同じところで詰まった方、あるいは「うちではこうだった」という方がいれば、コメントで教えていただけると嬉しいです。私もまだ全部の原因を解明できたわけではないので、情報は集めたいと思っています。
この構成で出した4本
本文で「4本リリースした」と書いたので、証拠として並べておきます。全部このWindows + Codemagic構成で、手元のMacでビルドしたものは1本もありません。
かわいいタイマー:勉強・ポモドーロ・キッチン(この記事のアプリ)

勉強・ポモドーロ・料理・ボードゲームに。
聴くtoノート

麻雀 偉人雀荘 - オフラインで一人打ち

申請カメラくん

ジャンルはバラバラですが、リリースの手順はどれも同じです。一度この構成を作ってしまえば、2本目以降は「pushしてビルドを回すだけ」になります。最初の1本の苦労は、ちゃんと後で回収できます。
