見出し画像

WindowsだけでiOSアプリを出す方法と、実際に踏んだ7つの罠|Intel Macが詰んだ話


手元にMacはあった。Intelだった。

iPhoneアプリを作ろうと思ったとき、最初に確認したのは「Macがあるか」でした。

ありました。MacBookがしかもMacbookPro。


Win中心生活で殆ど使ってなかったので、新品同様

これで勝ったと思ったんですが、そんなに甘くはなかった。そのMacはIntel製で、macOS Ventura以降のアップデートに対応していなかったのです。

「まあOSが古いだけでしょ」と思うじゃないですか。思いますよね。私も思いました。でもここから、なかなかよくできた三段構えの罠が始まります。

  1. AppleはXcodeが動くmacOSのバージョンを縛っている。 新しいXcodeは新しいmacOSでしか動かない

  2. macOSが上がらなければXcodeも上がらない。 Intel機はある世代でアップデートが打ち切られる

  3. 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審査へ提出


Codemagic+TestFlightを連携で快適なリリース環境DA!

証明書もプロビジョニングプロファイルも、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本もありません。

かわいいタイマー:勉強・ポモドーロ・キッチン(この記事のアプリ)


3Dの女の子が声でカウントダウンしてくれるタイマー。
勉強・ポモドーロ・料理・ボードゲームに。


聴くtoノート


オフライン文字起こし・AI議事録・話者分離。通信せず端末内で処理します。


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

広告なし・初心者も安心。偉人25人がしゃべる本格麻雀。




申請カメラくん

日時・場所がのこる申請用カメラ。工事写真や現地確認の記録に。


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






いいなと思ったら応援しよう!