根据 Collection 视图中的使用日期对数据进行分段的有效方法

Efficient way of sectioning data based on date for usage in Collection View

我正在尝试根据用户的照片库图片按创建日期升序在 Collection 视图中划分部分。我正在使用这种方法,这种方法显然非常慢,尤其是当图片数量很多时。

首先,我按排序顺序获取 PHAssets:

let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
inFetchResult = PHAsset.fetchAssets(with: allPhotosOptions)

然后我将资产复制到数组中:

inFetchResult.enumerateObjects { (asset, index, stop) in
            let yearComponent = Calendar.current.component(.year, from: asset.creationDate!)
            let monthComponent = Calendar.current.component(.month, from: asset.creationDate!)
            let monthName = DateFormatter().monthSymbols[monthComponent - 1]

            var itemFound = false
            for (index, _) in self.dateArray.enumerated() {

                if self.dateArray[index].date == "\(monthName) \(yearComponent)" {
                    self.dateArray[index].assets.append(asset)
                    itemFound = true
                    break
                } else {
                    continue
                }
            }
            if !itemFound {
                self.dateArray.append((date: "\(monthName) \(yearComponent)", assets: [asset]))
            }

        }

然后我使用这个数组作为我的数据源。

有更好的方法吗?我试过字典,但它们改变了 objects 的顺序。我还考虑过找到一种方法,仅在资产将要显示在视图中时才将资产添加到我的 dateArray 中,但是,collection 视图需要预先知道部分的总数,因此我必须遍历所有图片并在加载视图之前检查它们的日期。

You can fetch photo assets and do all the sorting logic in background thread like in the below code, once you will done with the heavy processing then you can access main Thread to update the UI.

let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]


DispatchQueue.global(qos: .userInitiated).async {
    let photos = PHAsset.fetchAssets(with: .image, options: nil)
    var result = [Any]()

    photos.enumerateObjects({ asset, _, _ in
        // do the fetched photos logic in background thread


    })

    DispatchQueue.main.async {
    //   once you will get all the data, you can do UI related stuff here like
    //   reloading data, assigning data to UI elements etc.
    }
}