[iOS] AsyncImageを使ってみた

最近、SwiftUI Viewにて画像読み込みとキャッシュする方法を調べてみながらKingFisherやNukeなどのライブラリーも取り入れてみたり、色々試しています。

今回はiOS15からサポートする「AsyncImage」を使ってみたので備忘録として書いていきます。

1. 画像読み込み

URLから画像を読み込むための基本的な書き方は、以下のようになります。

AsyncImage(url: URL(string: "https://example.com/icon.png"))

また、画像をロードしている際はplaceholderを指定することもできます。
私はぐるぐる回るProgressViewを入れてみました。

import SwiftUI

struct ContentView: View {
    let url = "https://source.unsplash.com/random"
    
    var body: some View {
        VStack {
            AsyncImage(url: URL(string: url)) { image in
                image
                    .resizable()
                    .frame(width: 300, height: 300)
            } placeholder: {
                ProgressView()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

2. AsyncImagePhase(エラー処理など)

URLからの読み込みだと必ずしもエラー処理を書かないといけないので、実際によく使われそうなのはこのパターンになるかと思います。

クロージャでAsyncImagePhaseを指定してエラーの場合どうするかを書きます。

// 正常
import SwiftUI

struct ContentView: View {
    let url = "https://source.unsplash.com/random"
    
    var body: some View {
        VStack {
            AsyncImage(url: URL(string: url)) { phase in
                if let image = phase.image {
                    image
                        .resizable()
                        .frame(width: 300, height: 300)
                } else if phase.error != nil {
                    Color.red
                } else {
                    ProgressView()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

エラーの場合が見たかったのでURLを間違ったURLに指定して赤色を出してみました。

// エラー
import SwiftUI

struct ContentView: View {
    let url = "https://source.unsplash.cm/random"
    
    var body: some View {
        VStack {
            AsyncImage(url: URL(string: url)) { phase in
                if let image = phase.image {
                    image
                        .resizable()
                        .frame(width: 300, height: 300)
                } else if phase.error != nil {
                    Color.red
                } else {
                    ProgressView()
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
赤色ちょっと怖いね

これで基本的な使い方は終わりです。
ちゃんと動いてそう!

最後に

AsyncImageが公開される前まではURLからの画像を読み込む際にURLSessionなどを使って非同期処理を行う必要があったため、ライブラリーを取り入れないと若干の手間がかかる作業が必要だったのですが、AsyncImageを使うと画像の読み込みはもちろん、エラー処理まで簡単にできちゃって大分便利な機能だな~と思いました。
キャッシュは別の処理が必要に見えますが、AsyncImageを用いたキャッシュ処理も後々やってみようと思ってます。

参考

https://developer.apple.com/documentation/swiftui/asyncimage/
https://developer.apple.com/documentation/swiftui/asyncimagephase

この記事が気に入ったらサポートをしてみませんか?