我目前正在开发一款适用于 iOS / macOS 的照片应用程序,但我正在努力使用 PhotoKit。
我确实创建了一个类来管理我所有的 PhotoKit 请求。
class PhotosAPI: ObservableObject {
@Published var all = PHFetchResult<PHAsset>()
@Published var allAlbums = PHFetchResult<PHAssetCollection>()
@Published var allSmartAlbums = PHFetchResult<PHAssetCollection>()
// Functions to get the Collections / Assets
}
这部分到目前为止正在工作,但现在我正在努力在我的视图中显示这些数据。
在我看来,我想在列表/网格中呈现所有资产
struct ShowImages: View {
@ObservedObject var photos = PhotosAPI()
var body: some View {
List(photos.all, id: \.self) { item in
Text("\(item)")
}
}
}
但我确实收到错误:
初始化程序“init(_:id:rowContent:)”要求“PHFetchResult”符合“RandomAccessCollection”
我今天一整天都在尝试解决这个问题,但没有成功,而且我在谷歌中找不到任何有用的东西。
有人知道如何让 PHFetchResults 循环它们吗?
最后我可以用下面的代码显示图片。但这对我来说看起来是非常糟糕的代码。我更喜欢直接循环 PHFetchResult。有谁知道我怎样才能完成这个工作?
ForEach(0..<photos.all.count) { index in
Text("\(photos.all.object(at: index).localIdentifier)")
}
您可以为
RandomAccessCollection
实现 PHFetchResult
或创建符合 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)
}
}
然后您将能够将
PHFetchResultCollection
与 ForEach
一起使用
let collection = PHFetchResultCollection(fetchResult: fetchResult)
var body: some View {
ForEach(collection, id: \.localIdentifier) {
...
}
}
您可以使用
enumerate
方法枚举获取的结果对象的项目,例如:
https://developer.apple.com/documentation/photokit/phfetchresult/1620999-enumerateobjects
试试这个。
extension PHFetchResult<PHAsset> {
func enumeratedPHAssets() -> [EnumeratedSequence<[PHAsset]>.Element] {
Array(
self.objects(
at: IndexSet(0 ..< self.count)
)
.enumerated()
)
}
}
像这样使用它:
Foreach(results.enumratedPHAssets, id: \.offset) { idx, asset in
<#T##View#>
}