Swift & Objective-C

[Swift応用 #9] Swift ABI安定性:2019年にアプリ容量が減った理由

2019年にSwift 5とiOS 12.2がリリースされた後、アプリ容量が減ったのはABI安定性のおかげです。各アプリが抱えていたSwiftランタイムがOSへ移った経緯と、モジュール安定性、@frozenのトレードオフを整理します。

読了 9 分
[Swift応用 #9] Swift ABI安定性:2019年にアプリ容量が減った理由のカバー画像

2019年春、Swift 5とともにiOS 12.2がリリースされると、不思議なことが起きました。何もしていないのにアプリ容量が数MBずつ減ったのです。 Swift ABI Stability and More

前回の記事 Swift応用 #8から続く内容です。

秘密は、リリースノートにあった簡潔な一文でした。ABI安定性を達成。

Swiftシリーズ最終回では、この出来事の全容を解説します。ABIとは何か、なぜ5年もかかったのか、何を可能にしたのか。

言語の歴史と内部構造が交わるテーマで、シリーズの締めくくりにふさわしい内容です。

ABIとは — バイナリ同士の約束

APIは誰もが知っています。ソースコードレベルの約束です。関数名や引数が何かを定めます。

ABI(Application Binary Interface)はその下の層、コンパイル済みバイナリ同士の約束です。

関数呼び出し時に引数をどのレジスタへ載せるか、structをメモリにどう配置するか(レイアウト編で見たあのサイズ)、シンボル名の付け方(マングリング)、メタデータの場所まで含みます。

なぜこの約束が重要なのでしょうか。異なる時点に異なるコンパイラでビルドされた2つのバイナリが、一緒に動作する必要があるからです。

アプリとOS内蔵ライブラリの関係は、まさにそれです。ABIがバージョンごとに変われば、Swift 5.0でビルドしたアプリはSwift 5.5ランタイムと通信できません。 Swift ABI Stability and More

Swift初期は実際にそうでした。バージョンごとにABIが変わったため、各アプリは使用したバージョンのSwiftランタイムと標準ライブラリを丸ごと持ち歩く必要がありました。

アプリごとに数MBの重複した荷物となり、OSは独自のフレームワークにSwiftを使えませんでした。システムフレームワークは将来のアプリとも通信する必要がありますが、その保証がなかったからです。

Swift 5のABI安定性宣言は、この約束を凍結した出来事です。呼び出し規約、型のレイアウト、マングリングが確定し、以降のバージョンは約束を守りながら進化します。 Swift ABI Stability and More

標準ライブラリはすぐにOSへ移行しました(アプリからなくなったため容量が減少)。AppleがSwiftUIのようなシステムフレームワークをSwiftで作る道も開かれました。

2019年の容量減少は、言語が成熟した証だったのです。 Swift ABI Stability and More

なぜ5年もかかったのか — 凍結の重み

「もっと早く凍結すればよかったのに」という疑問には、凍結のコストを考える必要があります。ABIを確定するとは、その時点の設計ミスまで永遠に背負うことだからです。

一度約束したレイアウトや規約は、既存のバイナリが世の中に存在する限り変更できません。

Swift 1〜4の激動を思い出してください。構文はバージョンごとに大きく変わりました。その時期に凍結していたら、今のSwiftは初期設計の牢獄に閉じ込められていたでしょう。 Swift ABI Stability and More

ジェネリックの実装が安定し、値型のレイアウト戦略が検証されるまで待ちました。Evolutionの手続き(哲学編第4回)で大きな設計論争が整理されるまでの5年間です。

数十年にわたるABIの慣性によってC++が改善案を退ける事例を見ると、この慎重さの価値が分かります。

各アプリが背負っていたSwiftランタイムのリュックがOS共通の柱へ移った前後比較
各アプリが背負っていたランタイムのリュックがOS共通の柱へ引っ越しました

第二の約束 — モジュール安定性とライブラリ進化

しかし、ABI安定性だけでは解決しない問題が1つ残ります。バイナリフレームワークの配布です。

Swift 5.0以前のコンパイラは、モジュールインターフェースをswiftmoduleというバイナリ形式でやり取りしていましたが、これはコンパイラのバージョンに依存していました。 Swift ABI Stability and More

Xcodeが1つ上がるだけで、配布済みSDKがすべて使えなくなる構造でした。

Swift 5.1のモジュール安定性がこの問題を解決します。テキストベースの安定したインターフェースファイル(.swiftinterface)が導入され、別バージョンのコンパイラでビルドしたフレームワークを読み込めるようになりました。 Swift ABI Stability and More

XCFrameworkでSDKを配布するエコシステム(決済・分析・地図SDK)は、この基盤の上に成り立っています。

これと対になる概念がライブラリ進化モードです。後から保存プロパティを追加しても既存アプリを壊さないようフレームワークをビルドするオプションですが、代償が興味深いものです。

このモードのpublic structは、レイアウトが確定していないresilient typeになります。クライアントはコンパイル時にサイズを知ることができず、間接アクセスのコストを負います。

レイアウト編で見た「サイズが分かれば速い」の正確な逆命題です。

そこで進化モードには@frozenという逃げ道があります。「この型のレイアウトは凍結する。その代わり直接アクセスを許可する」という宣言です。標準ライブラリのIntやOptionalが@frozenなのはこのためです。

アプリ開発者にとっての実質的な意味はこうです。アプリターゲットとソース配布パッケージ(SwiftPMの大半)にはこのモードは不要で、有効にすると不利になります。

バイナリでSDKを配布する側だけが有効にするオプションです。「BUILD_LIBRARY_FOR_DISTRIBUTIONとは何ですか?」という疑問への答えがこの段落です。

まとめ — シリーズを貫く1つの物語

ABIがSwiftシリーズの最後なのには理由があります。ここまで扱ってきた概念がすべて、この地点で合流するからです。

値型のレイアウト(値編・レイアウト編)が凍結されたため、structはバイナリ境界を越えられます。witness table(ディスパッチ編)の形式が確定したため、プロトコルはフレームワークAPIになりました。

そしてEvolutionの手続き(哲学編第4回)が設計を成熟させたからこそ、凍結する自信が持てました。

型で安全性を、明示でコストを(unsafe・any・@unchecked)、そして階段で複雑さを(Progressive Disclosure)。

これらの原則が構文層からバイナリ層まで一貫して貫かれていること。それがシリーズ全体で伝えたかったことです。

Swiftは今もEvolutionフォーラムで次の階段を作っています。このシリーズが、その変化を自分で読み解くための地図になればと思います。ここで終わります。

進化可能なフレームワークと@frozenで凍結された構造体のアクセス速度を対比するイラスト
進化の柔軟性か、凍結の速度か。@frozenがそのスイッチです

まとめ

  • ABIはバイナリ同士の約束(呼び出し規約・レイアウト・マングリング)であり、Swift 5(2019年)で凍結されました。そのおかげで標準ライブラリがOSへ移りアプリ容量が減り、AppleはSwiftUIをSwiftで作れるようになりました。
  • 凍結に5年かかったのは、設計ミスまで永遠に背負う決断だったからです。ジェネリック、レイアウト、Evolutionの手続きが成熟するのを待った時間でした。
  • Swift 5.1のモジュール安定性(.swiftinterface)が、XCFrameworkを中心とするバイナリフレームワークのエコシステムを切り開きました。
  • ライブラリ進化モードは「フレームワークが進化してもアプリが壊れない」代わりに間接アクセスのコストを負う取引で、@frozenがその逃げ道です。アプリターゲットには不要なオプションです。
  • シリーズの結論:安全の型付け、コストの明示、複雑さの階段化というSwiftの原則は、構文からバイナリまで一貫しています。 Swift ABI Stability and More

出典と確認基準

  • Swift ABI Stability and More — Swift.org · 公式発表 · 確認日 2026-08-17 · 根拠:Swift 5のABI安定性、OSランタイム搭載、アプリ容量の変化

あわせて読みたい

Swift応用シリーズ