在不耗尽内存的情况下检索图像
Posted
技术标签:
【中文标题】在不耗尽内存的情况下检索图像【英文标题】:Retrieve Images Without Running Out Of Memory 【发布时间】:2016-01-26 05:54:11 【问题描述】:我正在尝试从用户的相机胶卷中检索图像,但遇到了内存不足的问题。我一次加载 50 张图像,但不幸的是,在几次加载后,它会耗尽内存并崩溃。我尝试将整个语句包装在自动释放池中,但事实证明这并不有效。这是我的代码...
func retrieveImages(thumbnail: Bool, indexOfLibrary: Int)
/* Retrieve the items in order of modification date, ascending */
var indexSet: NSIndexSet!
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate",
ascending: false)]
/* Then get an object of type PHFetchResult that will contain
all our image assets */
let assetResults = PHAsset.fetchAssetsWithMediaType(.Image,
options: options)
if totalPostsCounted == false
assetResults.enumerateObjectsUsingBlock (object: AnyObject!, count: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
if object is PHAsset
self.totalPosts = count
else
self.totalPostsCounted = true
if thumbnail == true
if totalPosts - libraryImageThumbnails.count < 50
allImagesLoaded = true
else
if firstTimeLoadedThumb == true
else
firstTimeLoadedThumb = true
else
if totalPosts - libraryImages.count < 50
allImagesLoaded = true
else
if firstTimeLoaded == true
else
firstTimeLoaded = true
if thumbnail == true
fiftyIncrementThumb = fiftyIncrementThumb + 50
increment = fiftyIncrementThumb
else
fiftyIncrement = fiftyIncrement + 50
increment = fiftyIncrement
let imageManager = PHCachingImageManager()
autoreleasepool () -> () in
assetResults.enumerateObjectsUsingBlock (object, count: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
if object is PHAsset
var imageSize: CGSize!
var array: NSArray!
if thumbnail == true
array = self.libraryImageThumbnails
else
array = self.libraryImages
autoreleasepool
if count >= array.count && count <= increment
if thumbnail == true
imageSize = CGSize(width: 100, height: 100)
else
imageSize = CGSize(width: self.cameraView.bounds.width, height: self.cameraView.bounds.height)
let asset = object as! PHAsset
let options = PHImageRequestOptions()
options.deliveryMode = .FastFormat
options.synchronous = true
imageManager.requestImageForAsset(asset,
targetSize: imageSize,
contentMode: .AspectFill,
options: options,
resultHandler: (image, _: [NSObject : AnyObject]?) -> Void in
if thumbnail == true
self.libraryImageThumbnails.append(image!)
else
self.libraryImages.append(image!)
)
我也试过这个,它返回 nil 并崩溃了......
let library = ALAssetsLibrary()
library.enumerateGroupsWithTypes(ALAssetsGroupAll, usingBlock: (group: ALAssetsGroup!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
group.enumerateAssetsUsingBlock( (asset, count: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
if asset != nil
self.libraryImageThumbnails.append(asset)
self.collectionTable.reloadData()
)
, failureBlock: (error: NSError!) -> Void in
)
如果您需要更多信息,请告诉我!谢谢!
【问题讨论】:
您需要做的是获取图像的 url,然后使用来自该 url 的dispatch_async
将图像加载到后台队列中。
@DhaivatVyas 如何使用文件 URL 从我的相机胶卷中检索图像?
【参考方案1】:
这是我在一个项目中所做的可能会有所帮助的事情:
一些属性:
let requestOptions = PHImageRequestOptions()
let fetchOptions = PHFetchOptions()
let cachingImageManager = PHCachingImageManager()
var assets: [PHAsset] = []
willSet
cachingImageManager.stopCachingImagesForAllAssets()
didSet
cachingImageManager.startCachingImagesForAssets(assets,
targetSize: PHImageManagerMaximumSize,
contentMode: .AspectFit,
options: self.requestOptions
)
func fetchPhotos()
requestOptions.resizeMode = PHImageRequestOptionsResizeMode.Exact
requestOptions.version = .Current
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat
requestOptions.synchronous = true
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: false)]
if #available(ios 9.0, *)
fetchOptions.fetchLimit = 50
else
// Fallback on earlier versions
fetchResults = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)
guard let fetchResults = fetchResults else
print("No PHAssets")
return
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) [weak self] in
fetchResults.enumerateObjectsUsingBlock object, index, stop in
let asset = object as! PHAsset
self?.assets.append(asset)
dispatch_async(dispatch_get_main_queue())
self?.photoCollectionView.reloadData()
【讨论】:
太棒了。乐于助人!【参考方案2】:试试这段代码,确保你导入<AssetsLibrary/AssetsLibrary.h>
,并将你的部署目标设为7.1。
Objective-C 代码
NSMutableArray *imageArray=[[NSMutableArray alloc] init];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop)
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
if (asset)
[imageArray addObject:asset];
NSLog(@"imageArray :: %@",imageArray);
];
failureBlock:^(NSError *error)
NSLog(@"error :: %@",error);
];
Swift 代码
var imageArray: [AnyObject] = [AnyObject]()
var library: ALAssetsLibrary = ALAssetsLibrary()
library.enumerateGroupsWithTypes(ALAssetsGroupSavedPhotos, usingBlock: (group: ALAssetsGroup, stop: Bool) -> Void in
group.enumerateAssetsUsingBlock((asset: ALAsset, index: Int, stop: Bool) -> Void in
if asset != nil
imageArray.append(asset)
NSLog("imageArray :: %@", imageArray)
)
, failureBlock: (error: NSError) -> Void in
NSLog("error :: %@", error!)
)
结果:
查看以下网址以供参考
https://***.com/a/15570221/4101371
https://***.com/a/25732673/4101371
https://***.com/a/32472476/4101371
您还可以使用 iOS 8 及更高版本的照片框架。 photos Framework
希望它会有所帮助。
【讨论】:
我刚刚尝试了其中一个建议,并编辑了我的问题以显示我这样做时发生了什么。 嗯,由于某种原因,当我尝试它可以工作时,但是当我尝试在 cellForRow 中设置图像时它崩溃了。【参考方案3】:设置下面的代码对我来说可以限制获取
let assetFetchOptions = PHFetchOptions()
assetFetchOptions.fetchLimit = 50
然后我只检索到 50 张照片,而我朋友的手机上只有 15,000 张!!
【讨论】:
以上是关于在不耗尽内存的情况下检索图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在不耗尽内存的情况下运行大型 Mahout 模糊 kmeans 聚类?
如何使用 Python Ray 在不耗尽内存的情况下并行处理大量数据?
如何在不耗尽内存的情况下部署包含 130,000 多个条目的脚本