Photos Framework. requestImageForAsset returning two results. Can't set image view

Read header of PHImageManager class

If -[PHImageRequestOptions isSynchronous] returns NO (or options is nil), resultHandler may be called 1 or more times. Typically in this case, resultHandler will be called asynchronously on the main thread with the requested results. However, if deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic, resultHandler may be called synchronously on the calling thread if any image data is immediately available. If the image data returned in this first pass is of insufficient quality, resultHandler will be called again, asychronously on the main thread at a later time with the "correct" results. If the request is cancelled, resultHandler may not be called at all. If -[PHImageRequestOptions isSynchronous] returns YES, resultHandler will be called exactly once, synchronously and on the calling thread. Synchronous requests cannot be cancelled. resultHandler for asynchronous requests, always called on main thread

So, what you want to do is that you make resultHandler to be called synchronously

PHImageRequestOptions *option = [PHImageRequestOptions new];
option.synchronous = YES;

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:target contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
        //this block will be called synchronously
}];

So your block will be called before ending your method

Good luck!


By default the requestImageForAsset works as asynchronous. So in your method the return statement will be executed even before the image is retrieved. So my suggestion is instead of returning the imageView, pass the imageView in that you need to populate the image:

func swipeView(swipeView: SwipeView!, viewForItemAtIndex index: Int, reusingView view: UIView!, yourImageView: UIImageView)
{
    let asset: PHAsset = self.photosAsset[index] as PHAsset

    var imageView: UIImageView! = yourImageView;

    let screenSize: CGSize = UIScreen.mainScreen().bounds.size
    let targetSize = CGSizeMake(screenSize.width, screenSize.height)


    var options = PHImageRequestOptions()
    options.resizeMode = PHImageRequestOptionsResizeMode.Exact

    PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in
        imageView.image = result;
    })
}

Note:

Another option is you can fire a notification with the result image from the resultHandler. But I prefer the above mentioned method.

Refer PHImageManager for more information.


resultHandler: block has info dictionary which may contain Boolean value for PHImageResultIsDegradedKey key, which indicates whether the result image is a low-quality substitute for the requested image.

Here's what documentation says:

PHImageResultIsDegradedKey: A Boolean value indicating whether the result image is a low-quality substitute for the requested image. (NSNumber)

If YES, the result parameter of your resultHandler block contains a low-quality image because Photos could not yet provide a higher-quality image. Depending on your settings in the PHImageRequestOptions object that you provided with the request, Photos may call your result handler block again to provide a higher-quality image.