我想从URL显示图像时遇到问题。我创建了一个用于下载数据并向前发布数据的类-ImageLoader
:
class ImageLoader: ObservableObject {
var didChange = PassthroughSubject<Data, Never>()
var data = Data() {
didSet {
didChange.send(data)
}
}
func loadData(from urlString: String?) {
if let urlString = urlString {
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.data = data
}
}
task.resume()
}
}
}
因此,我在屏幕上使用的ImageView
结构中使用它。
struct ImageView: View {
var urlString: String
@ObservedObject var imageLoader: ImageLoader = ImageLoader()
@State var image: UIImage = UIImage(named: "homelessDogsCats")!
var body: some View {
ZStack() {
Image(uiImage: image)
.resizable()
.onReceive(imageLoader.didChange) { data in
self.image = UIImage(data: data) ?? UIImage()
}
}.onAppear {
self.imageLoader.loadData(from: urlString)
}
}
}
我的问题是,如果我只运行项目,则图像不会更改,并且默认情况下仅显示image UIImage(named: "homelessDogsCats")
。
如果我在其中添加断点
onAppear {
self.imageLoader.loadData(from: urlString)
}
然后向前走,图像就显示出来了。
我在另一个视图中也遇到了同样的问题,该视图通常不显示URL中的Image
,但有时会显示。
答案 0 :(得分:1)
尝试使用@Published
-则不需要自定义PassthroughSubject
:
class ImageLoader: ObservableObject {
// var didChange = PassthroughSubject<Data, Never>() <- remove this
@Published var data: Data?
...
}
并在您的视图中使用它:
struct ImageView: View {
var urlString: String
@ObservedObject var imageLoader = ImageLoader()
@State var image = UIImage(named: "homelessDogsCats")!
var body: some View {
ZStack() {
Image(uiImage: image)
.resizable()
.onReceive(imageLoader.$data) { data in
guard let data = data else { return }
self.image = UIImage(data: data) ?? UIImage()
}
}.onAppear {
self.imageLoader.loadData(from: urlString)
}
}
}
注意:如果您使用的是 SwiftUI 2 ,则可以使用@StateObject
代替@ObservedObject
和onChange
代替onReceive
。 / p>
struct ImageView: View {
var urlString: String
@StateObject var imageLoader = ImageLoader()
@State var image = UIImage(named: "homelessDogsCats")!
var body: some View {
ZStack() {
Image(uiImage: image)
.resizable()
.onChange(of: imageLoader.data) { data in
guard let data = data else { return }
self.image = UIImage(data: data) ?? UIImage()
}
}.onAppear {
self.imageLoader.loadData(from: urlString)
}
}
}