I'm currently working on a photos app for iOS / macOS and I'm struggling with PhotoKit.
I did create a class where I manage all my PhotoKit requests.
class PhotosAPI: ObservableObject {
@Published var all = PHFetchResult<PHAsset>()
@Published var allAlbums = PHFetchResult<PHAssetCollection>()
@Published var allSmartAlbums = PHFetchResult<PHAssetCollection>()
// Functions to get the Collections / Assets
}
This part is working so far but now I'm struggeling with showing those data in my View.
In my View I would like to present all assets in a List / Grid
struct ShowImages: View {
@ObservedObject var photos = PhotosAPI()
var body: some View {
List(photos.all, id: \.self) { item in
Text("\(item)")
}
}
}
But I do get an error:
Initializer 'init(_:id:rowContent:)' requires that 'PHFetchResult' conform to 'RandomAccessCollection
I did try all day today to fix this but I wasn't successful and I couldn't find anything useful in google.
Does anyone have an idea how I can get PHFetchResults to loop over them?
At the end I was able to show the pictures with below code. But this looks like very bad code to me. I would prefer to loop directly over the PHFetchResult. Does anyone know how I can get this done?
ForEach(0..<photos.all.count) { index in
Text("\(photos.all.object(at: index).localIdentifier)")
}
You can implement RandomAccessCollection
for PHFetchResult
or create wrapper that conforms RandomAccessCollection
.
struct PHFetchResultCollection: RandomAccessCollection, Equatable {
typealias Element = PHAsset
typealias Index = Int
let fetchResult: PHFetchResult<PHAsset>
var endIndex: Int { fetchResult.count }
var startIndex: Int { 0 }
subscript(position: Int) -> PHAsset {
fetchResult.object(at: fetchResult.count - position - 1)
}
}
Then you will be able to use PHFetchResultCollection
with ForEach
let collection = PHFetchResultCollection(fetchResult: fetchResult)
var body: some View {
ForEach(collection, id: \.localIdentifier) {
...
}
}