是否有可靠的方法在 SwiftUI 中缓存来自 URL 的图像?

问题描述 投票:0回答:0

我用这个 LureListView 显示图像列表。您会注意到我在 .onAppear 修饰符中监听实时数据库更改。问题是,一旦我使用 AddLureToListView 向 Firebase 添加新图像,图像就会出现,但当我左右滚动时,它就会消失。我也会发布一个简短的视频。如果有任何代码我需要展示更多我能做到的。

视频链接

LURELISTVIEW:

import SwiftUI

struct LureListView: View {
    @StateObject private var viewModel = LureListViewModel()
    
    var body: some View {
        ZStack {
            Color(K.ColorName.newCatchViewBackground)
                .ignoresSafeArea(.all)
            if viewModel.lures.isEmpty {
                EmptyStateFishLogView()
            } else {
                ScrollView {
                    ForEach(viewModel.luresByType.sorted(by: { $0.type < $1.type }), id: \.type) { lures in
                        Text(lures.type)
                            .foregroundColor(Color(K.ColorName.greenMainColor))
                            .padding(.leading)
                            .padding(.top, 50)
                            .padding(.bottom, 15)
                            .font(.system(.largeTitle, design: .rounded, weight: .bold))
                            .frame(maxWidth: .infinity, alignment: .leading)
                        ScrollView(.horizontal, showsIndicators: false) {
                            LazyHGrid(rows: [GridItem(.flexible())]) {
                                ForEach(lures.lures) { lure in
                                    CacheAsyncImage(url: URL(string: lure.gearImageURL)!) { phase in
                                        switch phase {
                                        case .success(let image):
                                            image
                                                .renderingMode(.original)
                                                .resizable()
                                                .aspectRatio(contentMode: .fill)
                                                .frame(width: 300, height: 180)
                                                .clipped()
                                                .cornerRadius(10)
                                                .padding(.leading, 20)
                                                
                                        case .failure(let error):
                                            ErrorView(error: error)
                                        case .empty:
                                            Image(K.ImageName.noFishImage)
                                                .resizable()
                                                .scaledToFill()
                                                .frame(width: 120, height: 120)
                                                .cornerRadius(10)
                                                .padding(.leading, 20)
                                                .overlay(
                                                    ProgressView()
                                                        .frame(width: 120, height: 120)
                                                )
                                        @unknown default:
                                            fatalError()
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        .navigationBarTitle("Lures")
        .onAppear {
            viewModel.listenToRealtimeDatabase()
        }
        .onDisappear {
            viewModel.stopListening()
        }
    }
}

添加列表视图:

import SwiftUI
import PhotosUI
import SwiftSpinner

struct AddLureToListView: View {
    
    @State private var selectedItems: [PhotosPickerItem] = []
    @State private var data: Data?
    @State private var gearImage: UIImage = UIImage(named: K.ImageName.noLureImage)!
    @State private var gearType: String = K.RawText.notSpecified
    @State private var selectedLureType = K.RawText.selectALureType
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        ZStack {
            Color(K.ColorName.newCatchViewBackground)
                .ignoresSafeArea()
            VStack {
                Text(K.RawText.addANewLure)
                    .font(.title)
                
                FishGearPhotoPickerView(selectedItems: $selectedItems, data: $data, selectedLureType: $selectedLureType)
                
                Button(K.ButtonText.save) {
                    if let data = data {
                        gearImage = UIImage(data: data) ?? UIImage(named: K.ImageName.noLureImage)!
                        
                        if selectedLureType == K.RawText.selectALureType {
                            gearType = K.RawText.notSpecified
                        } else {
                            gearType = selectedLureType
                        }
                        SwiftSpinner.show(K.SpinnerText.savingLureToList)
                        StorageManager.shared.saveGearToFirbaseStorage(gearImage: gearImage, gearType: gearType, completion: { success in
                            if success {
                                DispatchQueue.main.async {
                                    SwiftSpinner.hide()
                                }
                                dismiss()
                            } else {
                                DispatchQueue.main.async {
                                    SwiftSpinner.hide()
                                }
#warning("Show user alert about issue saving to firebase")
                                print("Unable to save lure to firebase")
                            }
                        })
                    }
                }
                .CustomButtonModifier(foregroundColor: Color(.label), height: 55)
            }
            Spacer()
        }
    }
}

我尝试了 SwiftUI AsyncImage,结果相同。

firebase-realtime-database swiftui image-caching
© www.soinside.com 2019 - 2024. All rights reserved.