SwiftUI异步加载XML解析所得图片不显示,同步加载正常如何解决?
问题根因
- 你创建
ImageLoader后立刻读取data属性生成图片,此时异步网络请求刚发起,data还是空值,存入Station的image自然为nil,无法显示。 - 你在
parser(_:didEndElement:)方法内创建的ImageLoader是局部变量,方法执行完毕后实例就会被释放,网络请求的回调没有持有者可以执行,所以你写的两个打印语句完全不会输出。
解决方案
推荐符合SwiftUI设计的常规方案:不在XML解析阶段下载图片,仅存储图片URL,在视图展示时再异步加载图片,代码修改如下:
1. 调整XML解析逻辑
删除解析阶段的图片下载代码,只存imageUrl即可:
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { if elementName == "item" { podcasts.append( Station( name: podcastTitle, detail: "Podcast", url: URL(string: podcastURL)!, image: nil, // 解析阶段不赋值,由视图层异步加载 imageUrl: podcastImage )) } }
2. 实现异步加载图片的自定义视图
在需要展示Station图片的SwiftUI视图中,监听ImageLoader的data变化自动刷新视图:
struct StationImageView: View { @StateObject private var loader: ImageLoader private let placeholder: UIImage? // 占位图,可自定义 init(url: URL, placeholder: UIImage? = nil) { _loader = StateObject(wrappedValue: ImageLoader(imageURL: url)) self.placeholder = placeholder } var body: some View { if let uiImage = UIImage(data: loader.data) { Image(uiImage: uiImage) .resizable() } else { // 加载中显示占位图 Image(uiImage: placeholder ?? UIImage(named: "placeholder")!) .resizable() } } }
3. 列表/展示页调用示例
在你展示Podcast列表的地方,直接传入图片URL即可:
List(podcasts) { station in HStack { StationImageView(url: URL(string: station.imageUrl)!) .frame(width: 50, height: 50) Text(station.name) } }
额外说明
如果你的项目最低支持iOS 15及以上版本,可以直接使用系统内置的AsyncImage,不需要自己实现ImageLoader逻辑,调用更简单:
AsyncImage(url: URL(string: station.imageUrl)!) { image in image.resizable() } placeholder: { Image("placeholder") .resizable() } .frame(width: 50, height: 50)
内容的提问来源于stack exchange,提问作者Leff
相关产品推荐
相关产品推荐

