【Swift】AsyncImageとは?使い方や引数の意味をわかりやすく解説

B!

SwiftUIでリモート画像を非同期に表示したいときに便利なのが AsyncImage です。

AsyncImageは、URLから画像をフェッチして表示するまでの流れ(読み込み中・成功・失敗)を、宣言的に簡潔なコードで表現できます。

この記事では AsyncImage の基本的な意味や使い方、主要な引数の意味、活用シーン、注意点までをわかりやすく丁寧に解説します。

AsyncImage とは?

AsyncImage は、指定した URL から画像を非同期で取得して SwiftUI のビュー階層に表示するためのコンポーネントです。

内部では非同期ダウンロードを行い、その進行状況に応じて表示内容を切り替えます。

表示状態は AsyncImagePhase(.empty/.success(Image)/.failure(Error))で表され、これを使って

  • 「読み込み中はローディング表示」
  • 「失敗時は代替表示」
  • 「成功時は画像表示」

と柔軟に分岐できます。

UIKitで同等のことをするには URLSession と UIImageView、キャッシュや状態管理を自前で組み合わせる必要がありましたが、SwiftUIの AsyncImage なら数行で同じ体験を実現できます。

具体例:最小構成からフェーズ管理、アニメーションまで

まずは最小の例です。

これだけで指定URLの画像を表示します(成功時は自動で画像が表示され、読み込み中や失敗時はシステム既定の挙動)。

次に、読み込み中プレースホルダーと失敗時ビューを自分で定義する、フェーズベースの使い方です。

フェードインなどのアニメーションを加える場合は、Transaction を渡します。

フェーズが変わるタイミングにアニメーションが適用されます。

主要な引数とその意味

AsyncImage は複数のイニシャライザがありますが、実務ではフェーズを扱えるイニシャライザが最も柔軟です。

主な引数は次の通りです。

引数名(代表的なイニシャライザ) 説明
url URL? 取得元の画像URL。nil の場合は何もフェッチしない(.empty のまま)。
transaction Transaction フェーズ遷移時に適用するアニメーション。省略時はアニメーションなし。
content(phase:) (AsyncImagePhase) -> some View 読み込み状態に応じて表示を切り替えるためのクロージャ。.empty / .success(Image) / .failure(Error) を受け取る。
scale(別イニシャライザ) CGFloat 画像のスケール係数(@2x/@3x 相当の解像度解釈)。省略可。
content(image:)/ placeholder(別イニシャライザ) (Image) -> Content / () -> Placeholder 成功時Imageとプレースホルダーを個別に受け取る古典的なスタイル。エラー時の分岐がしづらいため、フェーズ型推奨。

使い方

典型的な使い方は「フェーズベースのイニシャライザ」という書き方を使う方法です。

これは「読み込み中」「成功」「失敗」の3つの状態ごとに、見た目を切り替えられる便利な書き方です。

特に大事なのは 表示する大きさを常に同じにしておくこと です。

もし読み込み中は小さくて、成功時の画像は大きい…というようにサイズが違うと、画面がガタガタ動いて不自然になります。

活用シーン

AsyncImage が役立つのは、実際のアプリでリモート画像を使いたいときです。

例えば SNS やニュースアプリのように、たくさんの画像をネット経由で読み込むケースでは欠かせません。

具体的にはこんな場面で使えます:

  • ニュースフィードやSNSタイムラインなど、ネットワーク越しに多数のサムネイルを並べるUI
  • プロフィール画像やリスト行のアイコンをリモートから取得して表示
  • ギャラリー/スライダー/カルーセルの画像を段階的に読み込み、読み込み中は骨組み(シマー)やプレースホルダーを表示
  • 詳細画面でのメインビジュアルをフェードイン表示して体感パフォーマンスを向上
  • 接続不良や404などの失敗時に、明確な代替表示や再試行ボタンを組み合わせる

注意点

とても便利な AsyncImage ですが、使うときにいくつか気をつけたいポイントがあります。

これを知らないと「思ったように動かない」「画面が崩れる」といったトラブルになりがちです。

チェックしておきたい注意点は次の通りです:

  • 要求のカスタマイズは不可:AsyncImage は URL 単体指定です。HTTPヘッダー付与や POST、認証トークンが必要なダウンロードは直接対応しません(URLSession で自前実装が必要)。
  • キャッシュ制御は限定的:システムの URL キャッシュに従います。独自のディスクキャッシュや細かな無効化ポリシーが必要ならサードパーティや自前ローダーを検討。
  • サイズ指定の必須性:Image はデフォルトでオリジナルサイズです。.resizable().scaledToFit().scaledToFill().frame(...) を組み合わせてレイアウトを固定しましょう。
  • プレースホルダーのレイアウトを揃える:読み込み中・失敗時にも同じ枠サイズを確保し、レイアウトジャンプ(画面のレイアウト(配置)が急にガタッと動いてしまう現象のこと)を避けると見栄えが安定します。
  • 重い画像のコスト:非常に大きい画像はデコード・描画コストが高くスクロール性能に影響します。サーバー側でのリサイズやサムネイル提供を推奨。
  • 再試行やキャンセル:標準の AsyncImage には再試行ボタンやキャンセルAPIはありません。必要に応じて URL を変える/明示的にビューを再生成するなどの工夫が必要。
  • 対応OS:iOS 15+ / iPadOS 15+ / macOS 12+ 以降が目安。プロジェクトのデプロイターゲットに注意。

まとめると、「基本的な使い方はすごく簡単だけど、細かい制御や重い処理には向かない」ので、その場合は URLSession などと組み合わせるのがおすすめです。

まとめ

今回は SwiftUI の AsyncImage について詳しく紹介しました。

  • AsyncImage は、URL からの画像取得を非同期・宣言的に扱えるコンポーネント
  • フェーズ(AsyncImagePhase)で読み込み中/成功/失敗を安全に分岐できる
  • Transaction と組み合わせてフェードインなどのアニメーションも簡単
  • 実運用ではサイズ指定・プレースホルダー整合・キャッシュ戦略を意識する
  • ヘッダー付きリクエストや細かなキャッシュ制御が必要な場合は URLSession などで自前実装を検討した方がいい

まずは「フェーズベースの書き方」に慣れるのがおすすめです。

ぜひAsyncImageを使いこなして、より便利なアプリを作ってくださいね!

最新の記事はこちらから