◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/アプリ開発
◇ アプリ開発/2026-05-30中級

iOSの壁紙アプリでサムネイル一覧のカクつきを消す — ImageIOダウンサンプリングの実装メモ

大量のサムネイルを並べるとスクロールがカクつき、メモリも膨らむ。原因はメインスレッドでのフルサイズ画像デコードでした。ImageIOによるダウンサンプリングとプリフェッチで、実測でメモリを約80%削減した過程をまとめます。

iOS115Swift48パフォーマンス33UICollectionViewImageIO

✦ プレミアム記事

サムネイルを並べた瞬間にスクロールが詰まる

私は2014年から個人開発を続けていて、壁紙アプリは累計5,000万ダウンロードを超えるまでになりました。長く運用していると、初期のコードがそのまま残っている箇所が必ず出てきます。今回つまずいたのもそこでした。

サムネイルの一覧画面で、画像が数十枚を超えたあたりからスクロールが目に見えてカクつくのです。指を離した後の慣性スクロールが小刻みに引っかかり、端末によってはメモリ警告まで出る。手元のiPhoneで計測すると、一覧を一度開いただけでアプリのメモリ使用量が約480MBまで跳ね上がっていました。スクロール中のフレームレートも40fps前後まで落ち込み、ProMotion対応端末の滑らかさが完全に殺されていました。壁紙という性質上、扱う画像が大きいことは分かっていましたが、サムネイルの表示にここまで食うのは明らかに何かがおかしい。

原因はメインスレッドでのフルサイズデコードだった

コードを追っていくと、原因は二つ重なっていました。

ひとつは、UICollectionView の cellForItemAt の中で画像を同期的にデコードしていたこと。UIImage(contentsOfFile:) は一見すると軽い処理に見えますが、実際にピクセルへ展開(デコード)されるのは画像が描画される瞬間です。つまりスクロールで新しいセルが出てくるたびに、メインスレッド上で重いデコードが走っていたわけです。これがフレーム落ちの直接的な原因でした。

もうひとつは、サムネイル表示なのにフルサイズ画像をそのまま読み込んでいたこと。表示領域はせいぜい一辺200ポイント程度なのに、3000ピクセル四方を超える元画像をメモリ上に展開していました。展開後のビットマップは「幅 × 高さ × 4バイト」で効いてくるので、たとえば3000×3000の画像は1枚で約36MBになります。これを画面ぶん何枚も保持すれば、あっという間に数百MBです。これがメモリ膨張の正体でした。

公式のサンプルでも UIImage(named:) や contentsOfFile: がよく登場しますが、一覧表示で大量に扱う場面では、このまま使うと破綻します。公式ドキュメントには「一覧では縮小してから持て」と明示されていないのが、この落とし穴にハマる人が多い理由だと思います。表示に必要なサイズまで「読み込む段階で」縮小しておくのが実務上の正解です。

✦

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

この記事の続きを読む

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

この記事で得られること
✦cellForItemAt の同期デコードでスクロールが詰まり、メモリが480MBまで膨らむ仕組みを理解できる
✦CGImageSourceCreateThumbnailAtIndex を使ったダウンサンプリングの実装コードと、各オプションの意味を習得できる
✦プリフェッチ・NSCache・セル再利用キャンセルまで含めた、メモリを約80%削減して60fpsを保つ構成を再現できる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

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

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

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

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

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

関連記事

◇ アプリ開発2026-10-15
adjustsFontSizeToFit で特定の1行だけ極小になるとき、疑うのは文字列ではなく枠の高さです
一覧の10行目だけ文字が4ptまで縮む。データも文字列も正常なのに起きる iOS の症状を、Yoga の丸めと縮小判定のソースで確かめ、Node で再現率を数えた記録です。
◇ アプリ開発2026-08-05
キー短縮で 19% 減らしても配信は 3% しか軽くならない — カタログ JSON の圧縮実測と配置換え
2万件の壁紙カタログJSONで5形式を実測。キー短縮はgzip後3.2%しか効かず、列指向への配置換えは26.8%減。Brotli・ページング・JSON.parse時間まで、配信サイズ設計の判断材料を数値で並べます。
◇ アプリ開発2026-04-26
Rork でネイティブ iOS アプリを作る — SwiftUI 生成から TestFlight 配信までの実践ワークフロー
Rork の新規 iPhone プロジェクトは Swift/SwiftUI で生成され、Rork Pro で App Store まで届きます。古い Expo プロジェクトとの見分け方、クレジットで見る費用、骨格プロンプト、実機確認、Xcode に降りる基準、TestFlight 提出までを手順で追います。