如何减少 PhotoKit 的内存使用?
How to reduce memory use with PhotoKit?
我正在使用 PhotoKit
从系统相册中获取照片并将它们放入 UICollectionView
。
对于UICollectionViewCell
,我是这样设置的:
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
在初始化我的 UICollectionView
时,我从 collection
获取照片 PHAsset
:仅 Camera Roll
:
PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
[fetchResult enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop) {
NSLog(@"ALBUM NAME: %@", collection.localizedTitle);
if ([collection.localizedTitle isEqualToString:@"Camera Roll"]) {
_fetchedPhotos = [PHAsset fetchAssetsInAssetCollection:collection options:nil];
_pickedStatuses = @[].mutableCopy;
NSMutableArray *assets = @[].mutableCopy;
_manager = [[PHCachingImageManager alloc] init];
_options = [[PHImageRequestOptions alloc] init];
_options.resizeMode = PHImageRequestOptionsResizeModeExact;
_options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
CGFloat scale = [UIScreen mainScreen].scale;
CGSize targetSize = CGSizeMake(layout.itemSize.width*scale, layout.itemSize.height*scale);
//I'm not sure if this api should be called here
[_manager startCachingImagesForAssets:assets targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options];
}
}];
然后我从上面的 PHFetchResult
请求 UIImage
像这样:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MYCell *cell = (MYCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"reuseCell" forIndexPath:indexPath];
CGFloat scale = [UIScreen mainScreen].scale;
CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
PHAsset *asset = _fetchedPhotos[indexPath.item];
[_manager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options resultHandler:^(UIImage *result, NSDictionary *info) {
cell.imageView.image = result;
}];
return cell;
}
但是当我 运行 它并足够快地滚动 UICollectionView
时,我发现内存使用变得像这样陡峭:
如果内存不够会死机,如何减少?
我现在所做的是
- 减少获取的
PHAsset
个对象的目标大小;
尝试采用缓存。我的代码如下:
CGFloat scale = 1.5; //or an even smaller one
if (!_manager) {
_manager = [[PHCachingImageManager alloc] init];
}
if (!_options) {
_options = [[PHImageRequestOptions alloc] init];
}
_options.resizeMode = PHImageRequestOptionsResizeModeExact;
_options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
NSRange range = NSMakeRange(0, _fetchedPhotos.count);
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range];
NSArray *assets = [_fetchedPhotos objectsAtIndexes:set];
CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale);
[_manager startCachingImagesForAssets:assets targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options];
现在即使我滚动 UICollectionView
足够快,最高内存也将少于 50 MB
,感谢 Caching
(我猜它是基于我的代码工作的)它没有那么大的波动,内存使用是这样的:
更新
根据另一个posthere,建议不要指定PHImageRequestOptions
对象。相反,您可以将其留给 iOS 来决定什么是最适合您的,以最好的质量和最少的时间呈现照片。
我建议查看我提到的答案 。这不仅可以帮助您进行缓存,而且 Apple 的 Photos Framework 示例可以帮助您解决任何问题。
我正在使用 PhotoKit
从系统相册中获取照片并将它们放入 UICollectionView
。
对于
UICollectionViewCell
,我是这样设置的:cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
在初始化我的
UICollectionView
时,我从collection
获取照片PHAsset
:仅Camera Roll
:PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; [fetchResult enumerateObjectsUsingBlock:^(PHAssetCollection *collection, NSUInteger idx, BOOL *stop) { NSLog(@"ALBUM NAME: %@", collection.localizedTitle); if ([collection.localizedTitle isEqualToString:@"Camera Roll"]) { _fetchedPhotos = [PHAsset fetchAssetsInAssetCollection:collection options:nil]; _pickedStatuses = @[].mutableCopy; NSMutableArray *assets = @[].mutableCopy; _manager = [[PHCachingImageManager alloc] init]; _options = [[PHImageRequestOptions alloc] init]; _options.resizeMode = PHImageRequestOptionsResizeModeExact; _options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic; CGFloat scale = [UIScreen mainScreen].scale; CGSize targetSize = CGSizeMake(layout.itemSize.width*scale, layout.itemSize.height*scale); //I'm not sure if this api should be called here [_manager startCachingImagesForAssets:assets targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options]; } }];
然后我从上面的
PHFetchResult
请求UIImage
像这样:-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { MYCell *cell = (MYCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"reuseCell" forIndexPath:indexPath]; CGFloat scale = [UIScreen mainScreen].scale; CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale); PHAsset *asset = _fetchedPhotos[indexPath.item]; [_manager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options resultHandler:^(UIImage *result, NSDictionary *info) { cell.imageView.image = result; }]; return cell; }
但是当我 运行 它并足够快地滚动 UICollectionView
时,我发现内存使用变得像这样陡峭:
如果内存不够会死机,如何减少?
我现在所做的是
- 减少获取的
PHAsset
个对象的目标大小; 尝试采用缓存。我的代码如下:
CGFloat scale = 1.5; //or an even smaller one if (!_manager) { _manager = [[PHCachingImageManager alloc] init]; } if (!_options) { _options = [[PHImageRequestOptions alloc] init]; } _options.resizeMode = PHImageRequestOptionsResizeModeExact; _options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic; NSRange range = NSMakeRange(0, _fetchedPhotos.count); NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range]; NSArray *assets = [_fetchedPhotos objectsAtIndexes:set]; CGSize targetSize = CGSizeMake(_layout.itemSize.width*scale, _layout.itemSize.height*scale); [_manager startCachingImagesForAssets:assets targetSize:targetSize contentMode:PHImageContentModeAspectFill options:_options];
现在即使我滚动 UICollectionView
足够快,最高内存也将少于 50 MB
,感谢 Caching
(我猜它是基于我的代码工作的)它没有那么大的波动,内存使用是这样的:
更新
根据另一个posthere,建议不要指定PHImageRequestOptions
对象。相反,您可以将其留给 iOS 来决定什么是最适合您的,以最好的质量和最少的时间呈现照片。
我建议查看我提到的答案