Reputation: 327
I'm trying to fetch thumbnail as well as some other information from PHAsset. Here is a simplified code snippet.
For all the images I retrieve from camera roll do:
static func fetchAsset(asset: PHAsset)
{
if(asset.mediaType == PHAssetMediaType.Image){
let screenScale: CGFloat = UIScreen.mainScreen().scale
let imageSize = CGSize(width: 100 * screenScale, height: 100 * screenScale)
let options: PHImageRequestOptions = PHImageRequestOptions()
options.deliveryMode = PHImageRequestOptionsDeliveryMode.FastFormat
options.resizeMode = PHImageRequestOptionsResizeMode.Fast
options.synchronous = false
PHImageManager.defaultManager().requestImageForAsset(asset,
targetSize: imageSize,
contentMode: PHImageContentMode.AspectFill,
options: options,
resultHandler: { (result, info) -> Void in
if (result != nil && result!.scale == screenScale) {
var newItemImage = MyImage(isLocal:true)
if let fname = asset.valueForKey("filename") as? String{
newItemImage.fileName = fname
}
newItemImage.thumbnail = result
asset.requestContentEditingInputWithOptions(PHContentEditingInputRequestOptions()) { (contentEditingInput, info) -> Void in
//Get full image
let url = contentEditingInput!.fullSizeImageURL
newItemImage.url = url
}
//DO SOMWTHING WITH IMAGE
}else
{
//DO SOMWTHING ELSE
}
})
}
}
I've got two problems at this stage:
Any input on these two problems will be highly appreciated.
Upvotes: 2
Views: 4761
Reputation: 7463
You could also use this extension that I wrote:
import Photos
extension PHAsset {
var thumbnailImage : UIImage {
get {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: self, targetSize: CGSize(width: 300, height: 300), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
thumbnail = result!
})
return thumbnail
}
}
}
Upvotes: 2
Reputation: 535159
It does the job twice for some reason
Because that's what it's supposed to do. Fetching images from the photo library takes time, as you've discovered. Therefore, the default behavior is we supply a low-resolution image as quickly as possible, just so you have something to display; we then call again, possibly several times, with better-quality versions of the image. Moreover, the fetch is being formed asynchronously. Thus, it is perfectly possible to end up with multiple fetch requests happening at once, which can cause your code to start stumbling over its own feet, as you've discovered.
If you don't like that, set the fetch options synchronous
to true
— but then you must make this whole call on a background queue! By doing this in a serial queue you can make sure that the calls are performed separately in turn, and each image will be delivered just once. Moreover, then (and only then) your PHImageRequestOptions.DeliveryModeFastFormat
will be obeyed. Don't forget to step back out to the main thread before doing anything with the image you receive!
Upvotes: 3