Search code examples
iosswiftswift3photophassetcollection

How to get all photos properly in Swift3 iOS(Why I get duplicated photos)


I want to list all photos from "My Photo Stream", here is my code:

private func fetchAssetCollection(){
    let result = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumMyPhotoStream, options: nil)
    result.enumerateObjects({ (collection, index, stop) in
        if let albumName = collection.localizedTitle {
            print("Album => \(collection.localIdentifier), \(collection.estimatedAssetCount), \(albumName) ")
        }

        let assResult = PHAsset.fetchAssets(in: collection, options: nil)

        let options = PHImageRequestOptions()
        options.resizeMode = .exact
        let scale = UIScreen.main.scale
        let dimension = CGFloat(78.0)
        let size = CGSize(width: dimension * scale, height: dimension * scale)

        assResult.enumerateObjects({ (asset, index, stop) in
            print("index \(index)")
            PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: options) { (image, info) in
                if let name = asset.originalFilename {
                    print("photo \(name) \(index) \(asset.localIdentifier)")
                }
            }

        })

    })
}



extension PHAsset {

var originalFilename: String? {

    var fname:String?

    if #available(iOS 9.0, *) {
        let resources = PHAssetResource.assetResources(for: self)
        if let resource = resources.first {
            fname = resource.originalFilename
        }
    }

    if fname == nil {
        // this is an undocumented workaround that works as of iOS 9.1
        fname = self.value(forKey: "filename") as? String
    }

    return fname
}

}

it works, but the problem is that it print duplicated record. It prints 329*2 records but actually I have 329 photos in my "My Photo stream".

photo IMG_0035.JPG 10 0671E1F3-CB7C-459E-8111-FCB381175F29/L0/001
photo IMG_0035.JPG 10 0671E1F3-CB7C-459E-8111-FCB381175F29/L0/001
......

Solution

  • From the documentation for PHImageManager requestImage:

    By default, this method executes asynchronously. If you call it from a background thread you may change the isSynchronous property of the options parameter to true to block the calling thread until either the requested image is ready or an error occurs, at which time Photos calls your result handler.

    For an asynchronous request, Photos may call your result handler block more than once. Photos first calls the block to provide a low-quality image suitable for displaying temporarily while it prepares a high-quality image. (If low-quality image data is immediately available, the first call may occur before the method returns.) When the high-quality image is ready, Photos calls your result handler again to provide it. If the image manager has already cached the requested image at full quality, Photos calls your result handler only once. The PHImageResultIsDegradedKey key in the result handler’s info parameter indicates when Photos is providing a temporary low-quality image.

    So either make the request synchronous or check the PHImageResultIsDegradedKey value from the info dictionary to see if this instance of the image is the one you actually wish to keep or ignore.