📌
【SwiftUI】AsyncImageにオートリロードを実装する
非同期で画像を取得中に画面遷移を行った場合、画像の取得はキャンセルされます。遷移先から遷移元に戻ってきた時に画像の取得を再開してくれれば便利なのですが、残念ながらAsyncImage
にそのような機能はありません。そのため自分自身でオートリロードを実装する必要があります。
下記のコードでは独自で定義したAutoReloadableAsyncImage
を再帰的に呼び出すことで、この悩みを解決しています。実際に試してみたい方はシミュレータでアプリを立ち上げた後、なるべく早く5回ほど遷移してみると分かりやすいと思います。
struct ContentView: View {
private let viewNum: Int
private let imageURL = URL(string: "https://picsum.photos/4500/3000")
init(viewNum: Int = 1) {
self.viewNum = viewNum
}
var body: some View {
NavigationStack {
Text("Here is View\(viewNum).")
.bold()
AutoReloadableAsyncImage(imageURL: imageURL)
.frame(height: 300)
NavigationLink("Next") {
ContentView(viewNum: viewNum + 1)
}
}
.font(.title2)
}
}
struct AutoReloadableAsyncImage: View {
let imageURL: URL?
var body: some View {
AsyncImage(
url: imageURL,
transaction: .init(animation: .easeIn(duration: 0.6))
) { phase in
switch phase {
case .empty:
ProgressView()
case .success(let image):
image
.resizable()
.scaledToFit()
case .failure(let error):
if error.localizedDescription == "cancelled" {
AutoReloadableAsyncImage(imageURL: imageURL)
#if DEBUG
.task { print("reloaded") }
#endif
} else {
Text(error.localizedDescription)
#if DEBUG
.task { print(error.localizedDescription) }
#endif
}
@unknown default:
EmptyView()
}
}
}
}
https://www.youtube.com/watch?v=RcSi94-DNwk&list=TLPQMDMxMjIwMjMydYN3R0o3hQ&index=1
Discussion