アプリ開発
React NativeとExpoを軸にしたアプリ設計の考え方、ストア用スクリーンショットなどの素材制作、パフォーマンス改善、リリース後の運用まで、個人開発でモバイルアプリを作り届けるための実践的な記事をまとめています。
購読が切れても広告が戻りませんでした。「いま ad-free でなければ false」と書いていた、判定の向きを直した記録
購読が失効しても広告非表示のままになる不具合の原因は、判定の向きの逆転でした。二系統の購入確認を待って合成し、失敗した回は前回を保つ部品を、手元で動かして確かめた記録です。
adjustsFontSizeToFit で特定の1行だけ極小になるとき、疑うのは文字列ではなく枠の高さです
一覧の10行目だけ文字が4ptまで縮む。データも文字列も正常なのに起きる iOS の症状を、Yoga の丸めと縮小判定のソースで確かめ、Node で再現率を数えた記録です。
EAS Build だけ「No matching variant」で落ちるとき、まず疑う手元の android/build
手元の Gradle は通るのに、EAS Build の Android だけが「No matching variant of project」で止まる。GitHub の報告を読み比べ、Windows で生成した autolinking のキャッシュが Linux のビルド機へ渡っていた経路と、ビルドを投げる前に確かめる診断スクリプトをまとめました。
App Review で「Guideline 2.1・白い画面」と言われたとき、Expo のリリースビルドで疑う3か所
TestFlight では開くのに、審査では「起動後に白い画面のまま」と差し戻される。Expo + EAS のリリースビルドで、環境変数の environment、secret の可視性、審査員の環境差の3点を順に切り分ける手順を、確認コマンドと診断コードつきでまとめました。
Expo Go で通知だけが届かない夜に、先に切り分ける3点と development build への最短の移り方
Android 実機の Expo Go でプッシュ通知が届かないとき、端末設定を疑う前に確かめる3点と、development build に移る最小の手順をまとめました。通知以外に Expo Go で試せないものの見分け方も添えます。
起動のたびに一瞬ログイン画面が出る expo-router アプリを、Protected routes と「まだ分からない」の三状態で組み直す
ログイン済みなのに起動直後にログイン画面が一瞬出る、ログアウトしても画面が変わらない。expo-router の Protected routes に Supabase の認証状態を「不明」込みの三つで渡し、_layout.tsx の置き場所まで含めて直した手順です。
落ちたはずなのに「固まる」と書かれる — Android のクラッシュが白い画面のまま残るとき
クラッシュレポートには例外が並ぶのに、利用者からは「固まる」としか報告されないことがあります。expo-updates と新アーキテクチャの組み合わせで Android の画面が白いまま残る仕組みと、復帰導線・異常終了の検知・原因の特定を順番に置いていく手順をまとめます。
prebuild が requires the standard Expo SDK 57 Swift AppDelegate で止まったとき、まず確かめる3行
iOS 27 のために ios.enableSceneSupport を有効にすると prebuild が止まることがあります。原因は SDK の版ではなく AppDelegate.swift の形でした。確かめる3行と、手で書くときに SDK 58 の手順を真似てはいけない理由をまとめます。
消したはずのトークンが再起動で戻る — SecureStore の削除失敗を検知する設計
サインアウト直後に getItemAsync が null を返しても、Android のディスクには値が残っていることがあります。削除の成否を読み出しで確かめていた実装を、戻り値で判断する形へ書き直した記録です。
Rork のリポジトリに置く最初の EAS Workflow と、失敗した回にだけ届かない通知
Rork から書き出したリポジトリに .eas/workflows を二本置くまでの手順と、needs でつないだ通知が失敗した回にだけ届かなくなる理由を、手元で走る検査スクリプトの実行結果つきで書き残します。
閉鎖テストの14日間は、待つ時間ではなく申請フォームに書く材料を集める時間です
Google Play の本番アクセスは、閉鎖テストで12人が連続14日以上 opt-in している状態から申請します。日数の数え方、トラックを通す順番、申請フォームが聞いてくる項目と、14日間に残しておく記録のかたちをまとめました。
アプリから外部の AI にユーザーの文章を送るとき、Play の「データの安全性」に何を書くか
外部の AI にユーザーの入力を渡すアプリで、Play のデータ安全性フォームの収集・共有・一時処理をどう区分するか。送信を一箇所に集める実装と、順序を誤ると消し漏れるマスキングの実測を添えて整理します。
eas.json に image を書かないままだと、SDK を上げた日に Xcode も pnpm も一緒に動きます
eas.json に image を書いていないビルドの既定は auto です。SDK エイリアスが1つ動くと Xcode・Node.js・pnpm・fastlane がまとめて入れ替わります。Xcode 27 が来る前に、自分のビルドが通ったイメージ名をログから拾い、固定するかどうかを決めるまでの手順です。
targetSdk を 36 にした後、依存ライブラリのどこを見るか
依存ライブラリの AndroidManifest を実際に6本開いて数えました。targetSdkVersion は1本も書かれておらず、代わりに12個の権限が入ってきます。提出前に何を見るべきかの整理です。
定期ジョブの取りこぼしに二週間気づけなかったのは、成功ログだけを見ていたからです
1日2回動くはずのアセット処理ジョブが半分しか発火せず、それでもログは全て成功でした。実行されなかった回を検出する台帳と、滞留の傾きを見る二つ目の番兵を、実行結果つきで組み立てます。
タブレットで縦固定が外れる Android 16 の変更と、Expo 側に用意されていない逃げ道
targetSdkVersion 36 では、sw600dp 以上の画面で screenOrientation が無視されます。app.json の orientation では戻せないこと、オプトアウトのプロパティが何を戻して何を戻さないかを、手元で確かめた出力とあわせて整理しました。
iOS 27 が正式版になる前に、予備の iPhone で公開中の Rork アプリを触っておく
iOS 27 の正式版は9月に来ます。開発者ベータが7回目まで進んだ今のうちに、予備の iPhone へベータを入れて公開中のアプリを触る手順と、見る順番、JS 側で先に潰せる箇所をまとめました。
サムネイルの移設は、配信中の版が旧パスを要求し続ける前提で組みました
サーバー側で画像の置き場所を変えても、ストアで配信中の版はビルド時のパス組み立てを持ち続けます。旧新どちらのパスでも 200 を返す双方向フォールバック、画像とカタログの更新順序、CDN を挟んだまま実応答を確かめる手順を、壁紙アプリの運用で使っている形のまま共有します。
targetSdk を 36 に上げたら 16 KB の警告が出ました。この2つは別の期限です
対象 API レベル36 の8月31日と、16 KB メモリページサイズの2027年2月1日は別の条件です。NDK を入れずに手元の AAB を検査する方法と、LOAD のずれと zip 境界のずれで直し方が変わることを、実際の出力とあわせて整理しました。
Apple の自動解析は、purpose string が書いてあるかではなく何に使うかを読んでいます
Rork や Expo で生成した iOS アプリを提出すると、Guideline 5.1.1 で「placeholder or otherwise insufficient purpose strings」と返されることがあります。キー名が示されないこの指摘の読み方と、app.json から文言を書き直すまでの手順をまとめました。
Rork のプロジェクトで targetSdkVersion 36 を通すまでに直した3か所
app.json に targetSdkVersion 36 と書いてあるのに、ビルドが読んでいた値は 35 でした。実効値を報告するスクリプトと、引き上げ・更新停止・延長申請の三択の分け方を残します。
グラフが壊れて見えるのは、データが多いときではなく最初の数日でした
記録アプリの折れ線グラフが、データの少ない最初の数日だけ線が消える。原因はY軸の幅が0になり座標がNaNになることでした。実測した挙動と、描画前に置く小さな正規化層を紹介します。
TestFlight の外部テストと段階公開、個人開発ではどちらに時間を使うか
Rork で作ったアプリを他人に配るとき、外部テスターを募集する道と段階公開に受け止めさせる道の二つがあります。個人開発の限られた時間をどちらに置くかを、配布が止まる条件と事前検証すべき三領域から整理しました。
壁紙の上の文字が読めるかを、端末ではなく取り込み時に決める — 判定指標を4つ測り比べた記録
壁紙の上に置くステータスバーや見出しが読めるかを、端末での画像解析ではなく取り込み時のメタデータで決める設計です。240枚のコーパスで判定指標を4つ実測し、縮小画像での判定が何と一致するのかまで記録しました。
キー短縮で 19% 減らしても配信は 3% しか軽くならない — カタログ JSON の圧縮実測と配置換え
2万件の壁紙カタログJSONで5形式を実測。キー短縮はgzip後3.2%しか効かず、列指向への配置換えは26.8%減。Brotli・ページング・JSON.parse時間まで、配信サイズ設計の判断材料を数値で並べます。
1.10.0 の端末が強制アップデートに落ちる — 最小サポートバージョン判定を4実装で実測する
リモート設定で最小サポートバージョンを引き上げるゲートを、バージョン比較の4実装で実測しました。localeCompare が同値と言い切る箇所、fail-open の境界、審査中バージョンを閾値にした事故までを記録しています。
生成した壁紙カタログのハッシュが毎回変わる — 非決定の出どころを5つ切り分ける
同じ画像フォルダから同じ catalog.json が出てこない。opendir の列挙順、JSON.stringify のキー並べ替え、照合順序、Unicode 正規化、非同期の完了順。1,225ファイルで一つずつ切り分けて、出力を1種類に固定するまでの実測記録です。
壁紙カタログに同じ絵が二度並んでいた — 知覚ハッシュの閾値を324枚で実測して決める
画像カタログの重複検出を、SHA-256・dHash・色相署名・ブロック署名の4通りで実測しました。dHash 単独では適合率0.9%。平坦な画像でハッシュが潰れる現象と、閾値ではなく正解ラベルの方が間違っていた顛末を、再現できるコードと数値で共有します。
1行も書かずに App Store 審査を一周する — ステッカーパックを申請の予行演習に使う
iMessage ステッカーパックはコードなしで App Store に提出できる数少ない枠です。収益にならない制約と引き換えに、申請工程を丸ごと一度通せます。画像仕様の落とし穴と、予行演習としての使い方をまとめました。
壁紙の段組みギャラリーにネイティブ広告を差し込む — 広告セルの寿命をプールで設計する
段組みギャラリーにネイティブ広告を1枚入れたところ、20分のスクロールでメモリが伸び続けました。リスト再利用と広告の寿命が噛み合わない理由から、プール方式の実装、差し込み間隔の決め方まで実測とともに残します。
壁紙を長押しして、プレビューと保存メニューを出す — Rork の Expo アプリで context menu を組む
壁紙ギャラリーのカードを長押ししても何も起きない。iOS利用者はプレビュー付きのメニューを期待します。Pressableだけでは届かない理由から、zeegoでのネイティブcontext menu実装、スクロールとの競合解消、保存・共有アクション、Android向けの自前フォールバックまで、動くコードでまとめます。
App Store のスクショは6.9インチだけ撮れば足りる — 多言語アプリの本数を減らす撮影パイプライン
App Store Connect が必須とするのは6.9インチiPhoneと13インチiPadの2枚だけです。Appleが小さい機種へ自動縮小する仕組みを前提に、fastlane snapshotとframeitで多言語スクショの撮影本数を減らす実務をまとめました。
App Store の新しい年齢別レーティングに答え直す — 複数アプリで実際に変わった項目とつまずき
13+・16+・18+が加わったApp Storeの新しい年齢別レーティングに、運用中の複数アプリで答え直した記録です。4つの新設質問カテゴリや最低年齢を自分で引き上げられる仕組み、Rorkで公開したアプリで実際に迷った項目と回答の手順を、つまずきも含めてまとめました。
高さの異なる画像を2列で美しく並べる—Rork の Expo アプリで壁紙ギャラリーを段組みにする
縦横比のばらつく画像を numColumns では美しく並べられない理由から、列の高さを見て振り分ける段組みアルゴリズム、FlashList の masonry での仮想化、依存を増やさない実装まで、壁紙ギャラリーを実コードで組みます。
ワンタイムコードの入力欄をExpoで作る — SMS自動入力とセグメント表示を両立させる
6桁の確認コードを入れる画面は、見た目こそ単純ですが、SMSの自動入力・貼り付け・1文字ずつの削除まで含めると意外と作り込みが必要です。iOSとAndroidの自動入力を最初に押さえ、単一のTextInputで崩れにくいセグメント表示を組む実装をまとめました。
Rork Max(Swift)と通常版(React Native)、どちらで作るか — 個人開発者のための意思決定フレーム
Rork Max のネイティブ Swift と通常版の React Native、どちらでアプリを作るかを迷ったときの判断軸を、コスト・機能境界・移行のしやすさから整理します。個人開発の視点で書いた意思決定フレームです。
Rork Max アプリで通信の切断と復帰に強くする — NWPathMonitor によるオフライン検知と再送設計
Rork Max のネイティブ Swift アプリで、電波が切れても壊れない通信設計を NWPathMonitor で組み立てます。オフラインの検知、Low Data Mode やモバイル回線の判定、復帰時の自動再送キューまで、動く Swift コードで示します。
Rork Max アプリに読み上げ機能を組み込む — AVSpeechSynthesizer の音声選択と発話中ハイライトの設計
Rork Max のネイティブ Swift アプリに読み上げ機能を組み込む実装メモです。AVSpeechSynthesizer の音声選択、発話中の単語ハイライト、オーディオセッションの設計、そして日本語で詰まりやすい落とし穴までまとめました。
Rork Max アプリに PDF の表示と書き出しを組み込む — PDFKit と ImageRenderer の使い分け
Rork Max のネイティブ Swift で PDFKit を使い、PDF の表示・検索・書き出しを実装します。UIGraphicsPDFRenderer と ImageRenderer の使い分け、パスワード保護、共有シート連携までの実装手順です。
Rork Max アプリでダウンロードをアプリ終了後も続ける — バックグラウンド URLSession の設計と再起動復帰
Rork Max のネイティブ Swift アプリで、アプリがサスペンド・終了されてもダウンロードを OS 側で継続させるバックグラウンド URLSession の設計を解説します。再起動復帰・resumeData・isDiscretionary の実測挙動まで動くコードで示します。