xcode iOS 8 从 PHAsset 快速加载图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27408374/
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
iOS 8 Load Images Fast From PHAsset
提问by Aggressor
I have an app that lets people combine up to 4 pictures. However when I let them choose from their photos (up to 4) it can be very slow even when I set image quality to FastFormat. It will take 4 seconds (about 1 second per photo). On highest quality, 4 images takes 6 seconds.
我有一个应用程序,可以让人们组合最多 4 张图片。但是,当我让他们从他们的照片(最多 4 张)中进行选择时,即使我将图像质量设置为 FastFormat 也会非常慢。这将需要 4 秒(每张照片约 1 秒)。在最高质量下,4 张图像需要 6 秒。
Can you suggest anyway I get get the images out faster?
无论如何,你能建议我更快地获取图像吗?
Here is the block where I process images.
这是我处理图像的块。
func processImages()
{
_selectediImages = Array()
_cacheImageComplete = 0
for asset in _selectedAssets
{
var options:PHImageRequestOptions = PHImageRequestOptions()
options.synchronous = true
options.deliveryMode = PHImageRequestOptionsDeliveryMode.FastFormat
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize:CGSizeMake(CGFloat(asset.pixelWidth), CGFloat(asset.pixelHeight)), contentMode: .AspectFit, options: options)
{
result, info in
var minRatio:CGFloat = 1
//Reduce file size so take 1/3 the screen w&h
if(CGFloat(asset.pixelWidth) > UIScreen.mainScreen().bounds.width/2 || CGFloat(asset.pixelHeight) > UIScreen.mainScreen().bounds.height/2)
{
minRatio = min((UIScreen.mainScreen().bounds.width/2)/(CGFloat(asset.pixelWidth)), ((UIScreen.mainScreen().bounds.height/2)/CGFloat(asset.pixelHeight)))
}
var size:CGSize = CGSizeMake((CGFloat(asset.pixelWidth)*minRatio),(CGFloat(asset.pixelHeight)*minRatio))
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
result.drawInRect(CGRectMake(0, 0, size.width, size.height))
var final = UIGraphicsGetImageFromCurrentImageContext()
var image = iImage(uiimage: final)
self._selectediImages.append(image)
self._cacheImageComplete!++
println(self._cacheImageComplete)
if(self._cacheImageComplete == self._selectionCount)
{
self._processingImages = false
self.selectionCallback(self._selectediImages)
}
}
}
}
回答by rickster
Don't resize the images yourself — part of what PHImageManager
is for is to do that for you. (It also caches the thumbnail images so that you can get them more quickly next time, and shares that cache across apps so that you don't end up with half a dozen apps creating half a dozen separate 500MB thumbnail caches of your whole library.)
不要自己调整图像大小——部分原因PHImageManager
是为你做这件事。(它还缓存缩略图,以便您下次可以更快地获取它们,并在应用程序之间共享该缓存,这样您最终不会有六个应用程序为整个库创建六个单独的 500MB 缩略图缓存。 )
func processImages() {
_selectediImages = Array()
_cacheImageComplete = 0
for asset in _selectedAssets {
let options = PHImageRequestOptions()
options.deliveryMode = .FastFormat
// request images no bigger than 1/3 the screen width
let maxDimension = UIScreen.mainScreen().bounds.width / 3 * UIScreen.mainScreen().scale
let size = CGSize(width: maxDimension, height: maxDimension)
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: size, contentMode: .AspectFill, options: options)
{ result, info in
// probably some of this code is unnecessary, too,
// but I'm not sure what you're doing here so leaving it alone
self._selectediImages.append(result)
self._cacheImageComplete!++
println(self._cacheImageComplete)
if self._cacheImageComplete == self._selectionCount {
self._processingImages = false
self.selectionCallback(self._selectediImages)
}
}
}
}
}
Notable changes:
显着变化:
- Don't ask for images synchronously on the main thread. Just don't.
- Pass a square maximum size to
requestImageForAsset
and use theAspectFill
mode. This will get you an image that crops to fill that square no matter what its aspect ratio is. - You're asking for images by their pixel size here, and the screen size is in points. Multiply by the screen scale or your images will be pixelated. (Then again, you're asking for
FastFormat
, so you might get blurry images anyway.)
- 不要在主线程上同步请求图像。只是不要。
- 将正方形最大尺寸传递给
requestImageForAsset
并使用该AspectFill
模式。这将为您提供一个裁剪以填充该正方形的图像,无论其纵横比是多少。 - 您在这里按像素大小要求图像,屏幕大小以磅为单位。乘以屏幕比例,否则您的图像将被像素化。(再说一次,您要求的是
FastFormat
,因此无论如何您可能会得到模糊的图像。)
回答by matt
Why did you say synchronous
? Obviously that's going to slow things way down. Moreover, saying synchronous
on the main thread is absolutely forbidden!!!! Read the docs and obey them. That is the primary issue here.
你为什么说synchronous
?显然,这会减慢速度。而且,synchronous
绝对禁止在主线程上说!!!!阅读文档并遵守它们。这是这里的主要问题。
There are then many other considerations. Basically you're using this call all wrong. Once you've removed the synchronous
, do not process the image like that! Remember, this callback is going to be called many timesas the image is provided in better and better versions. You must not do anything time-consuming here.
然后还有很多其他的考虑。基本上你使用这个调用都是错误的。一旦你删除了synchronous
,不要像那样处理图像!请记住,随着图像以越来越好的版本提供,此回调将被多次调用。你不能在这里做任何耗时的事情。
(Also, why are you resizing the image? If you wanted the image at a certain size, you should have asked for that size when you requested it. Let the image-fetcher do the work for you.)
(另外,你为什么要调整图像大小?如果你想要一个特定大小的图像,你应该在请求时要求这个大小。让图像提取器为你做这项工作。)