SwiftUI列表和延迟加载

时间:2020-07-15 20:59:56

标签: ios swift swiftui

我创建了一个简单的SwiftUI应用程序,该应用程序在列表中显示来自网络的图像。所有图像均在后台加载。至此,所有工作均按预期进行。但是,如果在加载过程中确实触发了一些State变量,那么我的所有单元格都将重新初始化。

让我们看看代码:

struct ImageView: View {

   @ObservedObject var imageLoader = ImageLoader()

   var body: some View {

        VStack {

            if self.imageLoader.isLoaded {

               DisplayImage(self.imageLoader.image)
            } else {

               Text("Loading...")
            }
        }
        .onAppear {

            self.imageLoader.loadImage()
        }
   }
}

struct TableView: View {
   
   @State var someTrigger: Bool = false;

    var body: some View {

       List {

           ForEach( someCollection, id: \.self) {

              ImageView()
           }
       }
    }
}

因此,如果在加载图像时触发了“ someTrigger”,则所有单元将被重新初始化,imageLoader将被重新初始化,.onAppear将不会被调用,图像将不会加载。

这是预期的行为吗?在那种情况下,我只是不能用某些后台任务来初始化我的模型?

谢谢。

2 个答案:

答案 0 :(得分:0)

我认为可以通过传递imageLoader而不是在视图本身中初始化为您解决。我实际上会建议使集合对象具有ImageLoader来更新某些@Published图像属性。尝试设置模型以完成所有繁重的工作,然后让视图仅声明模型的每个状态应具有的状态。

答案 1 :(得分:0)

SwiftUI 2.0

使用StateObject包装器,它将不允许重新创建加载器

struct ImageView: View {
   @StateObject var imageLoader = ImageLoader()

SwiftUI 1.0

可能的解决方案(可能取决于您的真实代码)是使ImageView显式地等于某个属性(例如,仅id),即。排除imageLoader本身。这可以使渲染引擎有机会在状态更改时不替换ImageView

例如

struct ImageView: View, Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool {
        lhs.url == rhs.url
    }

    let url: URL // some unique property
    @ObservedObject var imageLoader = ImageLoader()

    // ... other code
}

并使用

   ForEach( someCollection, id: \.self) {
      ImageView().equatable()       // << here !!
   }