swiftui 同时加载多张图片

时间:2021-03-17 14:45:18

标签: image swiftui load

目前我有一个从 url 加载图像的图像加载器。但是所有的图像都是一样的。有谁知道我做错了什么?

@State var outfitimage: UIImage?

// .... a lot of lines in between ..... 


        LazyVGrid(columns: columns, spacing: 20) {
            ForEach(data, id: \.id) { item in
                VStack {
                    Text(item.displayname.capitalized)
                        .font(.title3)
                    Image(uiImage: outfitimage!)
                        .resizable()
                        .cornerRadius(15)
                }
                .onAppear{
                    downloadimage(imagename: item.user)
                }

            }
        }


// .... a lot of lines in between ....

func downloadimage(imagename: String) {
    let userimage = "outfits/" + (imagename) + ".jpg"

    Storage.storage().reference().child(userimage).getData(maxSize: 1048576) {
        (imageDataMyOutfit, Error) in
        if let Error = Error {
            print("an error accured: " + Error.localizedDescription)
        } else {
            if let imageDataMyOutfit = imageDataMyOutfit {
                self.outfitimage = UIImage(data: imageDataMyOutfit)
            } else {
                print("couldn't unwrap image data")
            }
        }
    }
}

它使用 Firebase 存储来存储所有图像。我真的不知道我做错了什么。

1 个答案:

答案 0 :(得分:1)

您只有一个带有 UIImage 的 @State 变量,因此每次从您的 downloadimage 函数加载新图像时,它都会覆盖该值。

您可以通过以下几种方式解决此问题:

  1. 使用 imagename 的键(您当前传递给 download image 的值和 UIImage 的值)制作字典。然后,从该字典中动态提取。我还考虑将所有这些移到 ObservableObject

  2. 使用@State 变量将每个 Image 封装在其自己的子视图中,以保持其加载状态。

第一个版本可能如下所示:

class ImagesLoader : ObservableObject {
    @Published var images : [String:UIImage] = [:]
    
    func downloadImage(imagename: String) {
        let userimage = "outfits/" + (imagename) + ".jpg"
        
        if self.images[imagename] != nil { return }
        
        Storage.storage().reference().child(userimage).getData(maxSize: 1048576) {
            (imageDataMyOutfit, Error) in
            if let Error = Error {
                print("an error accured: " + Error.localizedDescription)
            } else {
                if let imageDataMyOutfit = imageDataMyOutfit, let uiImage = UIImage(data: imageDataMyOutfit) {
                    DispatchQueue.main.async {
                        self.images[imagename] = uiImage
                    }
                } else {
                    print("couldn't unwrap image data")
                }
            }
        }
    }
}


struct ContentView: View {
    @StateObject var imagesLoader = ImagesLoader()
    
    var body: some View {
        LazyVGrid(columns: columns, spacing: 20) {
            ForEach(data, id: \.id) { item in
                VStack {
                    Text(item.displayname.capitalized)
                        .font(.title3)
                    if let uiImage = imagesLoader.images[item.user] {
                        Image(uiImage: uiImage)
                            .resizable()
                            .cornerRadius(15)
                    }
                }
                .onAppear{
                    imagesLoader.downloadImage(imagename: item.user)
                }
            }
        }
    }
}

请注意,除非存在图像,否则我不会显示 Image 视图。在您当前的代码中,通过使用 ! 强制解包 UIImage?,如果它曾经是 nil,您将导致崩溃。

还值得指出的是,在实际情况下,您可能希望对图像进行更多缓存、错误处理等。您可以研究一个框架来执行此操作,例如 https://github.com/SDWebImage/SDWebImageSwiftUI< /p>