SwiftUI中List内Button的HStack加载网络图片显示黑色问题
解决SwiftUI中List按钮内网络图片不显示的问题
嘿,我来帮你搞定这个网络图片无法渲染的问题!你的代码里核心问题在于同步加载网络图片的方式,这在SwiftUI的渲染流程里会出问题,咱们一步步来解决:
问题根源
你当前的artwork()函数是在主队列(UI线程)里用Data(contentsOf:)同步请求网络图片,这会导致两个关键问题:
- 同步网络请求会阻塞UI线程,让界面卡顿甚至无响应
- SwiftUI的View是值类型,每次视图刷新都会重新调用
artwork(),反复发起无效请求,而且图片加载完成后无法正确触发视图更新
而系统图片和本地资源不需要网络请求,所以能正常显示。
解决方案1:使用SwiftUI官方的AsyncImage(iOS 15+)
这是最简单的方案,苹果在iOS15之后提供了AsyncImage组件,专门用来异步加载网络图片,自动处理加载、失败、占位状态:
替换你原来的artwork()函数,直接在View里使用AsyncImage:
import SwiftUI struct ContentView: View { let artworkURL = URL(string: "https://via.placeholder.com/150")! var body: some View { List { Button(action: { // 你的按钮点击逻辑 print("按钮被点击啦") }) { HStack { AsyncImage(url: artworkURL) { phase in switch phase { case .empty: // 加载中的占位视图 Image(systemName: "book") .frame(width: 50, height: 50) case .success(let image): // 加载成功的图片 image .resizable() .scaledToFit() .frame(width: 50, height: 50) case .failure: // 加载失败的占位视图 Image(systemName: "exclamationmark.triangle") .frame(width: 50, height: 50) @unknown default: Image(systemName: "book") .frame(width: 50, height: 50) } } // 其他信息 Text("按钮标题") } } } } }
解决方案2:兼容iOS 15以下版本
如果需要支持更低版本的iOS,咱们可以用ObservableObject来异步加载图片,手动管理加载状态:
- 创建图片加载器类:
import SwiftUI import Combine class ImageLoader: ObservableObject { @Published var image: UIImage? private var cancellable: AnyCancellable? deinit { cancellable?.cancel() } func load(url: URL) { cancellable = URLSession.shared.dataTaskPublisher(for: url) .map { UIImage(data: $0.data) } .replaceError(with: UIImage(systemName: "book")) .receive(on: DispatchQueue.main) .assign(to: \.image, on: self) } }
- 在ContentView里使用这个加载器:
struct ContentView: View { let artworkURL = URL(string: "https://via.placeholder.com/150")! @StateObject private var imageLoader = ImageLoader() var body: some View { List { Button(action: { // 你的按钮点击逻辑 print("按钮被点击啦") }) { HStack { if let image = imageLoader.image { Image(uiImage: image) .resizable() .scaledToFit() .frame(width: 50, height: 50) } else { Image(systemName: "book") .frame(width: 50, height: 50) } // 其他信息 Text("按钮标题") } .onAppear { imageLoader.load(url: artworkURL) } } } } }
这两种方案都能解决你遇到的网络图片不显示问题,而且不会阻塞UI,还能正确处理加载状态~
内容的提问来源于stack exchange,提问作者user208685
相关产品推荐
相关产品推荐

