The following has a SwiftUI Hang for several seconds.
This code is copy-pasted and makes up one of the tabs of my simple app. Hang occurs once when first showing this tab.
Number of images is ~150; image size 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)
}
}
}
}
I thought that using the LazyHGrid
only a handful would be loaded initially (only one and almost a half fit on screen currently).
How I can improve performance?
By default the fetch will load every filteredData
into memory even if it is not being displayed. You need to use a custom NSFetchRequest
with includesPropertyValues
set to false
and then make a subview that takes the object and accesses filteredData
causing it only to be loaded for that one object when it appears (body
will be called at this time). You would also benefit from a predicate that searches for non-nil data that would help avoid the if
in your body
which can cause slow downs. E.g. something like:
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: photo)
}
...
See my answer to another question for more detail.