以下 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
最初只会加载少数内容(目前屏幕上只有一个半)。
如何提高绩效?
我遇到了类似的问题,因为我无法设置本机 LazyViews 的一些详细信息。
因此,我必须创建自己的 LazyView,尽管它不太方便。
我无法提供完整的代码,但这里有一些细节:
.onAppear
显示倒数第二个/第三个项目,则加载下一个项目或下一组项目。.onAppear
将在项目显示后立即调用,即使它只有 1% 可见。因此,您可能需要使用附加代码为其设置一些偏移量(例如,如果该项目显示超过 30%,则加载下一个项目)附注
如果您不支持 iPad,那么 1920x1080 的尺寸对于 iPhone 来说就太大了
默认情况下,即使未显示,提取也会将每个
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)
}
...