使用Publish的ObservableObject中的SwiftUI ObservableObject在Xcode 12中的downloadURL回调后不更新视图

时间:2020-09-20 19:07:49

标签: swift swiftui

我在SwiftUI中遇到问题,我的downloadURL图像未发布到可见项的视图中。当我滚动时,不在视图中的SwiftUI元素会得到更新。问题在于,最初呈现视图时,图像URL为“”(空白)。因此,将按预期呈现默认图像。虽然,当downloadURL任务完成时,图像不会更新。如果我在属性上使用willSet和/或objectWillChange.send()的组合,则会更新1张图片,但只会更新1张。

高流量:

  • 从Firebase获取系列数据文件
  • 将系列文件数据转换为modelView中的Series对象
  • 对于每个Series对象,从Firebase异步获取图像

这是查看代码

import SwiftUI
import struct Kingfisher.KFImage
import Firebase

struct SeriesView: View {
    
    // Firebase auth
    @EnvironmentObject var authState: AuthenticationState
    
    // Listen for view model state changes, i.e. series
    @ObservedObject var seriesList = SeriesList()
        
    private func signoutTapped() {
        authState.signout()
    }
    
    // search bar
    @State var searchText = ""
    @State var isSearching = false
    
    // firebase
    //@State private var imageURL = URL(string: "")
    @State private var imageURLString = ""
    let storage = Storage.storage()
    
    // view boday
    var body: some View {
        NavigationView {
            ScrollView {
                SearchBar(searchText: $searchText, isSearching: $isSearching)
  
                LazyVGrid(columns: [
                    GridItem(.flexible(minimum: 100, maximum: 200), spacing: 16, alignment: .top),
                    GridItem(.flexible(minimum: 100, maximum: 200), spacing: 16, alignment: .top),
                    GridItem(.flexible(minimum: 100, maximum: 200), spacing: 16)
                ], alignment: .leading, spacing: 16, content: {
                    // filter for search entry
                    ForEach(seriesList.seriesArray//) { series in
                                .filter({"\($0.uniqueId)".contains(searchText)
                                                            || "\($0.recordName)".contains(searchText)
                                                            || "\($0.seriesName)".contains(searchText)
                                                            || "\($0.fromYear)".contains(searchText)
                                                            || "\($0.toYear)".contains(searchText)
                                                            || searchText.isEmpty}), id: \.self) { series in
                        SeriesInfo(series: series)
                    }
                }).padding(.horizontal, 12)
            }
            .navigationBarTitle(kMyToyBoxText)
            .navigationBarItems(trailing: Button(action: signoutTapped, label: {
                Image(systemName: "person.circle")
                Text("Logout")
            }))
        }
    }
}
struct SeriesInfo: View {
    
    let series: Series
    
    var body: some View {
        NavigationLink(
            destination: DetailView(series: series.seriesName)) {
            VStack(alignment: .leading, spacing: 4) {
                KFImage(URL(string: series.imageFirebaseURLString))
                    .onSuccess { r in
                    }
                    .onFailure { error in
                    }
                    .placeholder {
                        // Placeholder while downloading.
                        kMyToyBoxLogoImage
                            .resizable()
                            .font(.largeTitle)
                            .opacity(0.3)
                            .scaledToFit()
                            .cornerRadius(22)
                    }
                    .cancelOnDisappear(true) // cancel if scrolled past
                    .resizable()
                    .scaledToFit()
                    .cornerRadius(22)
                Text(series.seriesName)
                    .font(.system(size: 10, weight: .semibold))
                    .padding(.top, 4)
                // convert to strings to avoid commas
                Text("\(String(series.fromYear)) - \(String(series.toYear))")
                    .font(.system(size: 9, weight: .regular))
                
                Spacer()
            }
        }
    }
}

图片Default image rendered

Scroll down and images are available

我的Series类(也尝试作为结构,但是它改变了行为)

// series class
class Series: Identifiable, ObservableObject {

    var id = UUID()
    let uniqueId: String
    let recordName: String
    let seriesName: String
    let fromYear: Int
    let toYear: Int
    let isMyToyBoxActive: Bool
    let logoImageName: String
    
    // generated data and needs to be published
    @Published var imageFirebaseURLString: String
    
    init (uniqueId: String, recordName: String, seriesName: String, fromYear: Int, toYear: Int, isMyToyBoxActive: Bool, logoImageName: String, imageFirebaseURLString: String = "") {
        self.uniqueId = uniqueId
        self.recordName = recordName
        self.seriesName = seriesName
        self.fromYear = fromYear
        self.toYear = toYear
        self.isMyToyBoxActive = isMyToyBoxActive
        self.logoImageName = logoImageName
        self.imageFirebaseURLString = imageFirebaseURLString
    }
}
extension Series: Hashable {

    public func hash(into hasher: inout Hasher) {
         hasher.combine(ObjectIdentifier(self).hashValue)
    }
}

extension Series: Equatable {

    public static func ==(lhs: Series, rhs: Series) -> Bool {
        return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
    }
}

ModelView代码-此代码将按预期的功能填充视图,但不包括downloadURL调用中的照片数据

// Series listener and data retriever
class SeriesList: ObservableObject {
    @Published var seriesArray = [Series]()
    
    init() {
        
       //... code removed for getting Series file data from Firebase

       let series: Series = self.getSeriesFromString(stringSeries: $0)
       self.seriesArray.append(series)

        // set the image
        let storageRefImage = storage.reference().child(kSeriesImageRoot)
        let seriesImageRef = storageRefImage.child(series.logoImageName)
                                
        // local image
        seriesImageRef.downloadURL { url, error in
            if let error = error {
            }
            else
            {
                series.imageFirebaseURLString = url!.absoluteString // <-- code to update the image URL
            }
        }

    }
}

1 个答案:

答案 0 :(得分:1)

在信息视图中也进行观察

struct SeriesInfo: View {
    
    @ObservedObject var series: Series     // << here !!
相关问题