Open-sourcing our photo layout for SwiftUI
LazyCollectionView – A modest attempt to port UICollectionView to SwiftUI.
The backstory
At Unsplash, we started using SwiftUI in our iOS app in 2020. Initially, we decided to build new views with SwiftUI, and whenever we redesigned a relatively simple view, we converted it from UIKit. This year, however, we stepped it up and began to convert more complex views.
One of the biggest challenges was converting our photo list view, showing photos in columns. We were using a UICollectionView
with a custom layout, and unfortunately, SwiftUI doesn't offer any equivalent that can lazy-load views.
LazyCollectionView is a modest attempt to solve this. Although we wrote it mainly to handle our specific use case in the Unsplash app, we tried to make it “open” enough so it could allow for any type of custom layout.
At WWDC 2022, Apple released the SwiftUI Layout API, which does not lazy-load its views; therefore, it is not recommended to display a large number of items. So we decided to release this component on GitHub.
How it works
There are three components.
LazyCollectionView
This is the view you use in your code. You embed it in a ScrollView
, which is convenient because you can mix it with other views, like a header and footer. You need to pass it the frame of its parent view so it can figure out which views should be displayed for the current scroll position. The views are laid out in a ZStack
that updates whenever the scroll offset changes.
LazyCollectionLayoutAttributes
It holds the position where single views are displayed in LazyCollectionView
.
LazyCollectionLayout
This is where you configure where views are positioned. You need to create a class that adopts this protocol.
Usage
Here is the typical way to use LazyCollectionView.
GeometryReader { geometryProxy in
let parentFrame = geometryProxy.frame(in: .local)
ScrollView {
LazyCollectionView(data: myArray,
layout: myCustomLayout,
parentFrame: parentFrame) { item in
ItemView(item)
}
}
}
Final words
We're excited to share this component because we hope it can be helpful to our fellow SwiftUI developers. Surely, it can be improved, so contributions are more than welcome!
Will someone attempt to write a CoverFlow layout?
You can find the project on Github at https://github.com/unsplash/swiftui-lazycollectionview.