避免 SwiftUI 挂起从 CoreData 加载图像列表

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

以下 SwiftUI 挂起几秒钟。

此代码是复制粘贴的,构成了我的简单应用程序的选项卡之一。第一次显示此选项卡时会发生一次挂起。

图像数量约为150;图像尺寸 1920x1080。

struct PhotosView : View
{
    @FetchRequest(sortDescriptors: [SortDescriptor(\Photo.date, order: .reverse)], animation: .default)
    private var photos: FetchedResults<Photo>

    @State private var gridHeight = 180.0

    var body: some View
    {
        VStack
        {
            ScrollView(.horizontal)
            {
                LazyHGrid(rows: [GridItem(.fixed(gridHeight))], alignment: .top, spacing: 0)
                {
                    ForEach(photos)
                    { photo in
                        if let data = photo.filteredData
                        {
                            Image(data: data)
                                .resizable()
                                .scaledToFit()
                        }
                    }
                }
                .frame(height: 200)
            }
        }
    }
}

我认为使用

LazyHGrid
最初只会加载少数内容(目前屏幕上只有一个半)。

如何提高绩效?

ios swiftui core-data freeze lazyhgrid
2个回答
0
投票

我遇到了类似的问题,因为我无法设置本机 LazyViews 的一些详细信息。
因此,我必须创建自己的 LazyView,尽管它不太方便。

我无法提供完整的代码,但这里有一些细节:

  • 设置加载项目的索引,例如5个项目或7个项目。
  • 如果使用
    .onAppear
    显示倒数第二个/第三个项目,则加载下一个项目或下一组项目。
  • .onAppear
    将在项目显示后立即调用,即使它只有 1% 可见。因此,您可能需要使用附加代码为其设置一些偏移量(例如,如果该项目显示超过 30%,则加载下一个项目)

附注
如果您不支持 iPad,那么 1920x1080 的尺寸对于 iPhone 来说就太大了


0
投票

默认情况下,即使未显示,提取也会将每个

filteredData
加载到内存中。您需要使用自定义
NSFetchRequest
并将
includesPropertyValues
设置为
false
,然后创建一个子视图来获取该对象并访问
filteredData
,导致它只在该对象出现时加载(
body 
此时会被调用)。您还将受益于搜索非零数据的谓词,这将有助于避免
if
中的
body
可能导致速度变慢。例如。像这样的东西:

struct PhotoView: View {
    @ObservedObject var photo: Photo

    var body: View {
        Image(data: photo.filteredData!)
            .resizable()
            .scaledToFit()
    }
}

// this could be moved to a lazy var in an extension of Photo
let fetchRequest: NSFetchRequest<Photo> = {
    let fr = Photo.fetchRequest()
    fr.predicate = NSPredicate(format: "filteredData != nil")
    fr.includesPropertyValues = false
    fr.sortDescriptors = [NSSortDescriptor(\Photo.date, ascending: false)]
    return fr
}

struct PhotosView : View
{
    @FetchRequest(fetchRequest: fetchRequest, animation: .default)
    private var photos: FetchedResults<Photo>

...
        ForEach(photos) { photo in
            PhotoView(photo: PhotoView)
        }
...
© www.soinside.com 2019 - 2024. All rights reserved.