SwiftUI多个AsyncImage组件意外相互影响,请求排查异常原因
问题描述
点击按钮后触发三个异步任务获取图片URL,分别传给三个AsyncImage组件,但只要有一张图片加载完成,另外两个的ProgressView就会消失,直接显示初始占位图。
相关代码
按钮点击逻辑
LargeButton(title: "Generate", disabled: isFetchingImage, backgroundColor: Color.blue, foregroundColor: Color.white) { focusedField = nil Task { fetching1 = true let getURL = try await networkFetch1() fetching1 = false imageURL1 = getURL ?? "" } Task { fetching2 = true let getURL = try await networkFetch2() fetching2 = false imageURL2 = getURL ?? "" } Task { fetching3 = true let getURL = try await networkFetch3() fetching3 = false imageURL3 = getURL ?? "" } }
AsyncImage组件
AsyncImage(url: URL(string: imageURL)) { phase in if fetching { ProgressView() } else if let image = phase.image { image .resizable() .scaledToFit() } else if phase.error != nil { Text("There was an error loading the image.") } else { Image("SMPTE_Color_Bars.svg") .resizable() .scaledToFit() } }
状态变量
@State private var fetching1: Bool = false @State private var fetching2: Bool = false @State private var fetching3: Bool = false @State private var imageURL1: String = "" @State private var imageURL2: String = "" @State private var imageURL3: String = ""
问题现象
点击按钮后三个AsyncImage都显示ProgressView,但任意一张图片加载完成后,另外两个的ProgressView会消失,直接显示初始占位图(SMPTE_Color_Bars.svg)。
问题原因与解决方案
原因分析
- 状态变量复用错误:每个
AsyncImage的加载状态判断,应该对应各自的fetching1/fetching2/fetching3,但你当前的代码里统一用了fetching变量(推测是复用了同一个状态,比如三个AsyncImage都用了fetching1)。当某一个fetchingX被设为false后,其他复用该变量的AsyncImage会直接退出ProgressView分支,跳到初始占位图逻辑。 - 自定义状态与AsyncImage原生状态冲突:
AsyncImage本身通过phase参数提供了完整的加载状态(空、成功、失败),额外维护fetchingX变量属于冗余操作,反而会打乱组件的原生状态逻辑。
解决方案
核心修改:移除自定义fetching变量,复用AsyncImage原生状态
删除所有fetching1/fetching2/fetching3状态变量,直接通过AsyncImage的phase判断加载状态,同时确保每个AsyncImage绑定对应独立的imageURL:
修改后的单个AsyncImage示例(对应第一个图片):
AsyncImage(url: URL(string: imageURL1)) { phase in switch phase { case .empty: // 未开始加载或正在加载时显示进度条 ProgressView() case .success(let image): image .resizable() .scaledToFit() case .failure(_): Text("加载图片出错") @unknown default: Image("SMPTE_Color_Bars.svg") .resizable() .scaledToFit() } }
按钮逻辑优化(可选)
把三个异步请求合并到同一个Task里,用并发语法简化代码:
LargeButton(title: "Generate", disabled: isFetchingImage, backgroundColor: Color.blue, foregroundColor: Color.white) { focusedField = nil Task { async let url1 = networkFetch1() async let url2 = networkFetch2() async let url3 = networkFetch3() do { let (result1, result2, result3) = try await (url1, url2, url3) imageURL1 = result1 ?? "" imageURL2 = result2 ?? "" imageURL3 = result3 ?? "" } catch { // 统一处理请求错误 } } }
修改后,每个AsyncImage会独立根据自身的加载状态显示对应内容,不会出现一个图片加载完成影响其他组件的问题。
内容的提问来源于stack exchange,提问作者erotsppa
相关产品推荐
相关产品推荐

