RORK LABEN
ENGINE — Rork Maxのコード生成はClaude CodeとClaude Opus 4.6を土台にしています。プロンプトの粒度を考えるうえで押さえておきたい前提ですSPLIT — Rork MaxはAppleプラットフォーム専用です。Androidも必要なら、React Nativeでクロスプラットフォームを生成する従来のRorkを選ぶことになりますDEVICE — Rork MaxはiPhone・iPad・Apple Watch・Vision Proを対象にできます。React Nativeからは届きにくかった領域まで生成対象に入りますCREDIT — 課金はクレジット制で、AIとのやり取り1回につき1クレジットを消費します。毎月1日にリセットされ、繰り越しはできませんPLAN — 無料は月35クレジット(1日5)、Juniorは月$25、Seniorは月$100、Rork Maxは月$200です。MVPの作り込みはSeniorが目安とされていますFUND — Rorkはa16zから280万ドルを調達し、月間743,000件を超える訪問を集めていますENGINE — Rork Maxのコード生成はClaude CodeとClaude Opus 4.6を土台にしています。プロンプトの粒度を考えるうえで押さえておきたい前提ですSPLIT — Rork MaxはAppleプラットフォーム専用です。Androidも必要なら、React Nativeでクロスプラットフォームを生成する従来のRorkを選ぶことになりますDEVICE — Rork MaxはiPhone・iPad・Apple Watch・Vision Proを対象にできます。React Nativeからは届きにくかった領域まで生成対象に入りますCREDIT — 課金はクレジット制で、AIとのやり取り1回につき1クレジットを消費します。毎月1日にリセットされ、繰り越しはできませんPLAN — 無料は月35クレジット(1日5)、Juniorは月$25、Seniorは月$100、Rork Maxは月$200です。MVPの作り込みはSeniorが目安とされていますFUND — Rorkはa16zから280万ドルを調達し、月間743,000件を超える訪問を集めています
記事一覧/開発ツール
開発ツール/2026-07-27上級

最低サポート iOS をいつ上げるか — 利用率ではなく、コードに残った分岐の数で決める

最低サポート OS の引き上げを利用率で判断すると、毎年同じ結論になって先送りが続きます。OS 分岐に注記を付けて棚卸しし、引き上げ先ごとに消せる分岐を数えるスクリプトと、引き上げ後に見る指標をまとめました。

Rork521Expo151React Native213保守設計2iOS109長期運用11

プレミアム記事

去年の秋も、その前の年の秋も、私は同じスプレッドシートを開いていました。

App Store Connect の OS バージョン別セッション比率を貼り付けて、いちばん古い世代の行を眺めます。0.9%。前年は 1.4%、その前は 2.1% でした。数字は毎年きれいに減っています。

それなのに、結論だけが毎年同じでした。「まだ切れないな」と打ち込んで、シートを閉じる。

3年目に気づいたのは、判断が鈍いのではなく、見ている指標が判断に向いていない、ということでした。利用率は「切ったら何人に届かなくなるか」を教えてくれます。けれど「切らなかったら自分が何を抱え続けるか」については、一言も教えてくれません。

利用率は「上げない理由」しか作らない

個人開発でアプリを複数本抱えていると、意思決定に使える時間は驚くほど短いものです。だからこそ、一つの数字で決めたくなります。

ところが利用率という数字は、構造的に片側にしか働きません。

閾値を 1% に置いたとします。0.9% になった年に上げられるかというと、上げられません。「あと少しで 0.5% になる、来年でいい」と考えるからです。0.5% になった年も同じで、今度は「たった 0.5% を切るために、わざわざリスクを取る意味があるのか」と考えます。分母が減るほど切る痛みは小さくなるはずなのに、心理的な閾値のほうが一緒に下がっていきます。

私の場合、壁紙アプリを6本並行で運用しています。判断を先送りするコストは、6本ぶん静かに積み上がっていました。

積み上がる場所は決まっています。OS の世代差を吸収するための分岐です。

// 実際に残っていたコードの一例(社内向けに簡略化しています)
if (Number.parseInt(String(Platform.Version), 10) >= 17) {
  await Sharing.shareAsync(uri, { UTI: 'public.png' });
} else {
  // 旧 OS では複数選択の共有シートが途中で閉じるので1枚ずつ
  for (const one of uris) {
    await Sharing.shareAsync(one, { UTI: 'public.png' });
  }
}

書いた当時は正しい分岐でした。問題は、この分岐が「いつ消せるのか」がコードのどこにも書かれていないことです。

半年後の自分は、この else 側がまだ必要なのかどうかを判断できません。判断できないから消せません。消せないから、次の改修のたびに両方の経路を確認することになります。

つまり、先送りの本当のコストは、切り捨てられなかったユーザー数ではなく、消せないまま残った分岐の数として現れていました。

それならば、その数を直接数えればいい。利用率の代わりに、そちらを判断の材料にする。そう考えて作ったのが、これから紹介する仕組みです。

分岐の在り処を、ひとつの規約に寄せる

最初にやったのは、OS 判定を書く場所と書き方を1つに決めることでした。

Platform.Version を各画面から直接読むのをやめて、比較関数に閉じ込めます。文字列比較で "9.0" > "10.0" になる事故を避けるため、要素ごとの数値比較にしています。

// src/lib/os.ts
import { Platform } from 'react-native';
 
const parse = (v: string | number): number[] =>
  String(v).split('.').map((n) => Number.parseInt(n, 10) || 0);
 
/** 実行中の iOS が target 以上かどうか。iOS 以外では常に false を返します。 */
export function atLeastIOS(target: string): boolean {
  if (Platform.OS !== 'ios') return false;
  const cur = parse(Platform.Version);
  const req = parse(target);
  for (let i = 0; i < Math.max(cur.length, req.length); i++) {
    const a = cur[i] ?? 0;
    const b = req[i] ?? 0;
    if (a !== b) return a > b;
  }
  return true;
}

この比較部分は、境界のケースを実際に流して確かめてあります。"17" のようにマイナー番号が省略された値、"17.0.1""17.1" のような桁数の違う比較、"16.4""16.4.1" の関係。7 パターンを流して、すべて期待どおりの結果になることを確認しました。この手の比較は、書いた直後には正しく見えて、桁が増えた瞬間に崩れます。

下限そのものは、参照される正本を1ファイルに置きます。

// src/config/supportMatrix.ts
// このアプリが公式に対応する OS の下限。ここだけが正本です。
// 変更するときは必ず os-sweep を走らせてから。
export const MIN_OS = {
  ios: '16.0',
  android: 31,
} as const;

そのうえで、OS 分岐には必ず注記を添える規約にしました。

// @drop-when ios>=17.0 -- 17.0 未満は共有シートの多重選択が途中で閉じる
if (!atLeastIOS('17.0')) {
  return <LegacyShareSheet uris={uris} />;
}

書式はごく単純です。@drop-when ios>=X に続けて -- のあとへ理由を書く。それだけです。

大事なのは形式の厳密さではなく、「いつ消せるか」と「なぜ書いたか」が、分岐のすぐ横に残ることです。この2つが揃っていれば、半年後の自分が消す判断をできます。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
OS 分岐を supportMatrix.ts と @drop-when 注記に寄せ、引き上げ先ごとに「消せる分岐が何箇所か」を数える棚卸しスクリプト全文
「下限を下回った消し忘れ」を CI で落とす終了コード設計と、GitHub Actions への組み込み方
引き上げ直後にクラッシュフリー率が良く見える理由と、その数字を成果として記録してはいけない理由
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-05-28
Rork アプリで iOS の BGTaskScheduler.submit が Error Code=1 で失敗するときの切り分け手順
Rork で作った iOS アプリで BGTaskScheduler.submit が Error Code=1 (Unavailable) を返してバックグラウンド更新が動かないときに、原因をひとつずつ潰していくための実用チェックリストです。
開発ツール2026-04-22
Rork で作った個人アプリを3年以上持たせるための保守設計 — アプリ老化と静かに戦う実践
Rork で作ったアプリを長く運用していくと、リリース直後には見えなかった「老化」が少しずつ現れてきます。OS 更新、ライブラリの破壊的変更、ユーザーの端末環境の変化。私が10年以上アプリを運営してきた経験と、Rork で作ったアプリを2年以上運用してきた中で、3年目以降も安定させるために大事にしている保守設計の考え方をまとめます。
開発ツール2026-04-02
Rork アプリにネイティブ共有機能を追加する — Share Sheet 実装ガイド
Rork アプリにネイティブ Share Sheet を実装する入門ガイド。テキスト・URL・画像のシェアから SNS 連携・ディープリンク連携まで、実際のコードで丁寧に解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →