SwiftUI 网络图像显示加载和错误的不同视图 [英] SwiftUI Network Image show different views on loading and error

查看:87
本文介绍了SwiftUI 网络图像显示加载和错误的不同视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想确保在下载图像时 ProgressView 是可见的,并且如果传递的 url 无效(空),则放置一个占位符.

I would like to make sure that when the image is being downloaded the ProgressView is visible and if the url being passed is invalid (empty), a placeholder is put.

我该怎么做?

代码:

import Foundation
import SwiftUI

// Download image from URL
struct NetworkImage: View {
    public let url: URL?
    var body: some View {
        Group {
            if let url = url, let imageData = try? Data(contentsOf: url),
               let uiImage = UIImage(data: imageData) {
                Image(uiImage: uiImage)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
            }
            else {
                ProgressView()
            }
        }
        
    }
}

struct NetworkImage_Previews: PreviewProvider {
    static var previews: some View {
        let url = [
            "",
            "http://google.com",
            "https://yt3.ggpht.com/a/AATXAJxAbUTyYnKsycQjZzCdL_gWVbJYVy4mVaVGQ8kRMQ=s176-c-k-c0x00ffffff-no-rj"
        ]
        NetworkImage(url: URL(string: url[0])!)
    }
}

推荐答案

你可以创建一个ViewModel来处理下载逻辑:

You can create a ViewModel to handle the downloading logic:

extension NetworkImage {
    class ViewModel: ObservableObject {
        @Published var imageData: Data?
        @Published var isLoading = false

        private var cancellables = Set<AnyCancellable>()

        func loadImage(from url: URL?) {
            isLoading = true
            guard let url = url else {
                isLoading = false
                return
            }
            URLSession.shared.dataTaskPublisher(for: url)
                .map { $0.data }
                .replaceError(with: nil)
                .receive(on: DispatchQueue.main)
                .sink { [weak self] in
                    self?.imageData = $0
                    self?.isLoading = false
                }
                .store(in: &cancellables)
        }
    }
}

并修改您的 NetworkImage 以显示占位符图像:

And modify your NetworkImage to display a placeholder image as well:

struct NetworkImage: View {
    @StateObject private var viewModel = ViewModel()

    let url: URL?

    var body: some View {
        Group {
            if let data = viewModel.imageData, let uiImage = UIImage(data: data) {
                Image(uiImage: uiImage)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
            } else if viewModel.isLoading {
                ProgressView()
            } else {
                Image(systemName: "photo")
            }
        }
        .onAppear {
            viewModel.loadImage(from: url)
        }
    }
}

然后你可以像这样使用它:

Then you can use it like:

NetworkImage(url: URL(string: "https://stackoverflow.design/assets/img/logos/so/logo-stackoverflow.png"))

(注意url 参数不是强制解包).

(Note that the url parameter is not force unwrapped).

这篇关于SwiftUI 网络图像显示加载和错误的不同视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆