【发布时间】:2020-02-21 20:46:35
【问题描述】:
我是 SwiftUI 和 Combine 的新手。我有一个简单的列表,我正在加载 iTunes 数据并构建列表。加载图像有效 - 但它们在闪烁,因为似乎我在主线程上的调度一直在触发。我不确定为什么。下面是图像加载的代码,然后是它的实现位置。
struct ImageView: View {
@ObservedObject var imageLoader: ImageLoaderNew
@State var image: UIImage = UIImage()
init(withURL url: String) {
imageLoader = ImageLoaderNew(urlString: url)
}
func imageFromData(_ data: Data) -> UIImage {
UIImage(data: data) ?? UIImage()
}
var body: some View {
VStack {
Image(uiImage: imageLoader.dataIsValid ?
imageFromData(imageLoader.data!) : UIImage())
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width:60, height:60)
.background(Color.gray)
}
}
}
class ImageLoaderNew: ObservableObject
{
@Published var dataIsValid = false
var data: Data?
// The dispatch fires over and over again. No idea why yet
// this causes flickering of the images in the List.
// I am only loading a total of 3 items.
init(urlString: String) {
guard let url = URL(string: urlString) else { return }
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else { return }
DispatchQueue.main.async {
self.dataIsValid = true
self.data = data
print(response?.url as Any) // prints over and over again.
}
}
task.resume()
}
}
这里是加载JSON等后实现的。
List(results, id: \.trackId) { item in
HStack {
// All of these image end up flickering
// every few seconds or so.
ImageView(withURL: item.artworkUrl60)
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 5))
VStack(alignment: .leading) {
Text(item.trackName)
.foregroundColor(.gray)
.font(.headline)
.truncationMode(.middle)
.lineLimit(2)
Text(item.collectionName)
.foregroundColor(.gray)
.font(.caption)
.truncationMode(.middle).lineLimit(1)
}
}
}
.frame(height: 200.0)
.onAppear(perform: loadData) // Only happens once
我不确定为什么图像会一遍又一遍地加载(至今)。我一定遗漏了一些简单的东西,但我绝对不知道组合的方式。任何见解或解决方案将不胜感激。
【问题讨论】: