iosswiftphasset

PHAsset.fetchAssets(withLocalIdentifiers with same order


let results: [PHPickerResult] = [1, 2, 3]
let identifiers = request.results.compactMap(\.assetIdentifier) // [1, 2, 3]
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil) // [1, 3, 2]

The problem is that PHAsset.fetchAssets shuffle the assets order. In comments I write an example how it can be returned. I haven't find any option to retrieve [PHAsset] with same order that identifiers. How to keep the order?


Solution

  • Workaround that I don't prefer, but didn't find better solution:

    extension PHFetchResult<PHAsset> {
        fileprivate func sortedByAssetIdentifiers(_ ids: [String]) -> [MediaPickerAsset] {
            guard count > 0 else {
                return []
            }
    
            var finalAssets = [Int: MediaPickerAsset]()
            for i in 0...count - 1 {
                let phAsset = object(at: i)
                if let pickerAsset = pickerAssetFromPHAsset(phAsset),
                   let indexByAssetIdentifier = ids.firstIndex(of: phAsset.localIdentifier) {
                    finalAssets[Int(indexByAssetIdentifier)] = pickerAsset
                }
            }
            return finalAssets.sorted(by: { $0.key < $1.key }).map(\.value)
        }
    }
    

    let identifiers = request.results.compactMap(\.assetIdentifier)
    let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: nil)
    let sortedAssets = fetchResult.sortedByAssetIdentifiers(identifiers)
    

    UPD after Sweeper comment

    fileprivate func sortedByAssetIdentifiers(_ ids: [String]) -> [MediaPickerAsset] {
        guard count > 0 else {
            return []
        }
    
        var finalAssets = Array(repeating: object(at: 0), count: ids.count)
        for i in 0...count - 1 {
            let phAsset = object(at: i)
            if let indexByAssetIdentifier = ids.firstIndex(of: phAsset.localIdentifier) {
                finalAssets[indexByAssetIdentifier] = phAsset
            }
        }
        return finalAssets.compactMap { $0.pickerAsset }
    }