URL的SwiftUI图像未显示

时间:2020-09-27 19:38:09

标签: swift swiftui

我想从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,但有时会显示。

1 个答案:

答案 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代替@ObservedObjectonChange代替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)
        }
    }
}