ios 照片框架。requestImageForAsset 返回两个结果。无法设置图像视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27670325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:08:53  来源:igfitidea点击:

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

iosuiimageviewuicollectionviewphotosframework

提问by Jonovono

So I am using the SwipeView library (https://github.com/nicklockwood/SwipeView) to show images using the Photos framework for iOS8.

所以我使用 SwipeView 库 ( https://github.com/nicklockwood/SwipeView) 使用 iOS8 的照片框架显示图像。

However, when I call the requestImageForAsset I notice I am getting two results, a thumbnail size, and the bigger size that I want. However, the bigger image isn't loaded (it's called async I understand) in time to return, so it returns the small image.

但是,当我调用 requestImageForAsset 时,我注意到我得到了两个结果,一个是缩略图大小,另一个是我想要的更大的大小。但是,较大的图像没有及时加载(我理解它称为异步),因此它返回小图像。

This code might make more sense.

这段代码可能更有意义。

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

    var imageView: UIImageView!

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


    var options = PHImageRequestOptions()
//        options.deliveryMode = PHImageRequestOptionsDeliveryMode.Opportunistic
    options.resizeMode = PHImageRequestOptionsResizeMode.Exact


    PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in
        println("huhuhuh")
        println(result.size)
        println(info)
        imageView = UIImageView(image: result)
    })
    println("setting view)
    return imageView
}

Here is the log output:

这是日志输出:

Enteredhuhuhuh
(33.5,60.0)
SETTING VIEW
huhuhuh
(320.0,568.0)

As you can see it returns the image view before the big image is recieved. How do I make it return this larger image so it's not showing the thumbnai?

如您所见,它在收到大图像之前返回图像视图。我如何让它返回这个更大的图像,所以它不显示缩略图?

Thanks.

谢谢。

回答by Tony

Read header of PHImageManagerclass

读取PHImageManager类的标题

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

如果 -[PHImageRequestOptions 是同步的] 返回 NO(或 options 为 nil),resultHandler 可能会被调用 1 次或多次。通常在这种情况下,resultHandler 将在主线程上与请求的结果异步调用。但是,如果deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic,则如果任何图像数据立即可用,则可以在调用线程上同步调用resultHandler。如果第一遍返回的图像数据质量不足,将再次调用 resultHandler,稍后在主线程上异步调用“正确”结果。如果请求被取消,则 resultHandler 可能根本不会被调用。如果 -[PHImageRequestOptions isSynchronous] 返回 YES,则 resultHandler 将在调用线程上同步调用一次。无法取消同步请求。

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

所以,你想做的是让你resultHandler被称为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 Midhun MP

By default the requestImageForAssetworks 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:

默认情况下,它requestImageForAsset以异步方式工作。因此,在您的方法中,即使在检索图像之前,也将执行 return 语句。所以我的建议是,不要返回 imageView,而是传递 imageView,因为您需要填充图像:

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.

另一种选择是您可以使用来自 resultHandler 的结果图像触发通知。但我更喜欢上面提到的方法。

Refer PHImageManagerfor more information.

有关更多信息,请参阅PHImageManager

回答by O Fen?meno

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

resultHandler:块具有信息字典,其中可能包含PHImageResultIsDegradedKey键的布尔值,指示结果图像是否是请求图像的低质量替代品。

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.

PHImageResultIsDegradedKey:一个布尔值,指示结果图像是否是所请求图像的低质量替代品。(NS编号)

如果是,则 resultHandler 块的结果参数包含低质量图像,因为照片还不能提供更高质量的图像。根据您随请求提供的 PHImageRequestOptions 对象中的设置,照片可能会再次调用您的结果处理程序块以提供更高质量的图像。

回答by Mrunal

Check the Apple Documentation for this method here.In that they are saying:

此处查看此方法的 Apple 文档他们说:

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.)

对于异步请求,照片可能会多次调用您的结果处理程序块。照片首先调用块以提供适合临时显示的低质量图像,同时它准备高质量图像。(如果低质量的图像数据立即可用,则可能会在该方法返回之前进行第一次调用。)

It might be taking time, in your case for fetching original size image. Otherwise your code seems okay to me.

在您的情况下,获取原始大小的图像可能需要时间。否则你的代码对我来说似乎没问题。

回答by sage444

You shouldn't rewrite imageView inside block, just set image to it and everything should work as you expect. To avoid showing two images you can check the size of image before assigning.

您不应该在块内重写 imageView,只需将图像设置为它,一切都应该按您的预期工作。为避免显示两个图像,您可以在分配前检查图像的大小。

var imageView =  UIImageView()
...
...
        PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: targetSize, contentMode: .AspectFill, options: options, resultHandler: {(result, info)in
                println("huhuhuh")
                println(result.size)
                println(info)
                if result.size.width > 1000 &&  result.size.height > 1000 { // add any size you want 
                     imageView.setImage(result)
                }
            })

回答by vaibby

try this will work for asynchronously too.

试试这也适用于异步。

[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:target contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
    if ([info objectForKey:@"PHImageFileURLKey"]) {
      //your code
    }
}];

回答by Hiren Panchal

Use below options, swift 3.0

使用以下选项,swift 3.0

publi var imageRequestOptions: PHImageRequestOptions{
let options = PHImageRequestOptions()
options.version = .current
options.resizeMode = .exact
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = true
options.isSynchronous = true
return options}