iOS 13 PHAsset.fetchAssets(withLocalIdentifiers:) returns only a subset of requested assets

Hi,


I need to resolve a bunch of PHAssets for localIdentifiers from a CoreData database with a mostly in iCloud stored Photos library.

Unfortunately on iOS 13 I don't receive all PHAssets when I try to fetch them and I don't receive any additional PHAssets via photoLibraryDidChange.

For me it looks like a regression from iOS 12 / Xcode 10 SDK builds where I didn't have that issue so reproducible.


When I leave the view controller and then fetch the remaining identifiers again a bit later I get another batch - usually 3 - more but usually not all of them. What do I need to do to resolve all identifiers?


Code is similar to:


class MyViewController {
  private var unresolvedAssets = [String: DCAsset]()
  private var resolveAssetsResult : PHFetchResult? = nil

  required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        PHPhotoLibrary.shared().register(self)
    }

    deinit {
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }

 var lesson: DCLesson! {
        didSet {
            unresolvedAssets.removeAll()
            for asset in lesson.assets {
                if asset.localAsset == nil {
                    unresolvedAssets[instance.localIdentifier] = asset
                }
            }
            
            let identifiers =  unresolvedAssets.keys.map{ return $0 }
            print("\(#function) resolving \(unresolvedAssets.count) assets: \(identifiers)")
            guard !unresolvedAssets.isEmpty else {
                return
            }

            let options = PHFetchOptions()
            resolveAssetsResult = PHAsset.fetchAssets(withLocalIdentifiers:identifiers, options: options)
            updateUnresolvedAssets( resolveAssetsResult! )
        }
    }

    func photoLibraryDidChange(_ changeInstance: PHChange) {
         DispatchQueue.main.sync {
            if let request = resolveAssetsResult,
                let changeDetails = changeInstance.changeDetails(for: request) {
                print( "Received changes: \(changeDetails.insertedObjects)" )
                updateUnresolvedAssets( changeDetails.fetchResultAfterChanges )
            }
        }
    }

    private func updateUnresolvedAssets( _ fetchResult: PHFetchResult ) {
        fetchResult.enumerateObjects{
            phAsset, _, _ in
            if let dcAsset = self.unresolvedAssets[phAsset.localIdentifier] {
                print("setting localAsset for \(dcAsset.assetIdentifier!)")
                dcAsset.localAsset = phAsset
                self.unresolvedAssets[phAsset.localIdentifier] = nil
            }
        }
    }
}


The following partially logs the result


lesson resolving 9 assets: ["7412823B-7CFB-4538-B380-4F1DCE861A50/L0/001", "3DC75596-22E7-4EAA-A92B-8301C3BB41B6/L0/001", "F6211272-CE49-47BE-9181-31ABF65E737D/L0/001", "C9EC1F1F-AE7E-440A-877A-B37AEE59C1A3/L0/001", "83736D97-94D4-417D-B537-E5C9B1B7BC67/L0/001", "9671C852-8777-4B44-BCF9-F5AFB6C5F8C3/L0/001", "B8EA862B-9B91-4F30-ABC5-82132E848DEA/L0/001", "4287A790-E0E7-494C-B047-7080CDF0E0B9/L0/001", "99C1EF0C-8F31-40C5-8D4A-999280D29739/L0/001"]

setting localAsset for 2018-06-22T15:02:25Z-140

setting localAsset for 2018-06-22T14:55:26Z-17

setting localAsset for 2018-06-22T15:05:13Z-28


*** Navigate back and forth


lesson resolving 6 assets: ["83736D97-94D4-417D-B537-E5C9B1B7BC67/L0/001", "084B2FBF-17F3-4520-ACD7-BCBFC3E74F0D/L0/001", "C60C84E8-E472-47FF-ADA3-DBAB82804792/L0/001", "3DC75596-22E7-4EAA-A92B-8301C3BB41B6/L0/001", "9671C852-8777-4B44-BCF9-F5AFB6C5F8C3/L0/001", "6EB5B8A7-92A3-4E18-AC7C-A86619CFEFF5/L0/001"]

setting localAsset for 2018-06-22T14:55:45Z-11

setting localAsset for 2018-06-22T14:54:53Z-9

setting localAsset for 2018-06-22T14:55:06Z-17


Received changes: []


*** Navigate back and forth


lesson resolving 3 assets: ["9671C852-8777-4B44-BCF9-F5AFB6C5F8C3/L0/001", "83736D97-94D4-417D-B537-E5C9B1B7BC67/L0/001", "287EBB67-BBBA-4FB9-AEAC-AC0ABD5A9132/L0/001"]

setting localAsset for 2018-06-22T14:57:32Z-36