少し前になりますが、WWDC21ではSwiftUIの新しい機能がたくさん紹介されていました。その中から今回は AsyncImage について説明していきます。XCode13以降、iOS15以降でしか使えないので、まだまだ業務などで使用はされないでしょうけど…。
いつも通り、Appleの公式ドキュメントを参考にしています。
AsyncImageとは
AsyncImageは画像を表示するビューです。指定したURLから画像を非同期で読み込んで表示することができます。
struct AsyncImage<Content> where Content : View
こんなふうに使用します。
struct ContentView: View {
var body: some View {
VStack{
AsyncImage(url: URL(string: "https://example.com/icon.png"))
.frame(width: 200, height: 200)
}
}
}
これだけで画像を取得でき次第表示してくれます。
placeholder が便利
さらにAsyncImageには以下のようなイニシャライザーがあります。
init<I, P>(url: URL?, scale: CGFloat = 1, content: @escaping (Image) -> I, placeholder: @escaping () -> P) where Content == _ConditionalContent<I, P>, I : View, P : View
これを使うと画像をロードしている間は別の画像などのView表示できます。ローディングのインジケーターを表示するのが一般的な使い方になるかと思います。
struct ContentView: View {
var body: some View {
VStack{
AsyncImage(url: URL(string: "https://example.com/icon.png")){ image in
image.resizable()
} placeholder: {
ProgressView()
}
.frame(width: 50, height: 50)
}
}
}
↑のように実装することで、ロード中はProgressViewを表示しておけます。
注意点
resizableなどの画像固有のモディファイアをAsyncImageに適用することはできません。そういったモディファイアを画像に適用したい場合は、上記のようにコンテンツクロージャーが取得するImageインスタンスに適用させる必要があります。
ロード失敗時の処理は?
ロードプロセスをより細かく制御したい場合は、AsyncImagePhaseを受信できるイニシャライザーを使いましょう。
init(url: URL?, scale: CGFloat = 1, transaction: Transaction = Transaction(), content: @escaping (AsyncImagePhase) -> Content)
これは、AsyncImagePhaseを受信してロード操作の状態を示すコンテンツクロージャーを取得し、適したビューを返すことができます。
struct ContentView: View {
var body: some View {
VStack{
AsyncImage(url: URL(string: "https://example.com/icon.png")) { phase in
if let image = phase.image {
image
} else if phase.error != nil {
Text("load error")
} else {
ProgressView()
}
}
.frame(width: 50, height: 50)
}
}
}
このように実装すれば、ロード中はプログレスビューを表示、ロード完了したら画像を表示、ロードに失敗したら「load error」と表示することができます。
めちゃめちゃ便利!
コメント