PhotoKit相册的性能优化
来源:互联网 发布:美工是什么职位类别 编辑:程序博客网 时间:2024/05/20 00:36
有关PhotoKit的基础知识,参考我的另一篇博文: 优雅的创建一个相册管理类。
这篇文章记录一下在实际项目中,自定义相册的优化工作。
之前的文章提到过,获取照片高清原图使用下面的方法:
PHImageManager *manger = [PHImageManager defaultManager]; PHImageRequestOptions * options = [[PHImageRequestOptions alloc] init]; options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat; options.synchronous = YES; options.resizeMode = PHImageRequestOptionsResizeModeFast; options.networkAccessAllowed = NO;[manger requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { //获取照片 result}];
在实际的使用过程中,如果涉及多张照片循环获取原图,就会出现内存大幅度上升的问题。通过Allcation就行内存检测的时候,发现正是该方法会占用很大的内存。
经过查找资料和自己的验证后,发现可以通过下面的方法获取图片。这样内存会稳定,就不会引起这样内存的问题。
[manger requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) { UIImage *image = [UIImage imageWithData:imageData]; //获取照片 image }];
该方法是获取先图片的二进制流,然后转化为UImage。
另外,对于滑动相册的时候,内存也会出现一定的增大,虽然不会造成明显的卡顿现象。
但官方也给出了PhotoKit的缓存机制接口,更好的优化内存,提升滑动的流畅性。
具体方法如下:
在当前拥有UICollectionView的视图控制器中:
@property (nonatomic, assign) CGRect previousPreheatRect;@property (nonatomic, strong) PHCachingImageManager *imageManager;
- (PHCachingImageManager *)imageManager{ if (_imageManager == nil) { _imageManager = [PHCachingImageManager new]; } return _imageManager;}- (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; [self updateCachedAssets];}- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ [self updateCachedAssets];}
该缓存方案的原理就是缓存frame范围内所对应的显示到cell上的照片的PHAsset对象。这样在滑动的时候直接读取缓存里面的数据,避免了反复根据index去给cell赋值的操作。
- (void)updateCachedAssets{ BOOL isViewVisible = [self isViewLoaded] && self.view.window != nil; if (!isViewVisible) { return; } // The preheat window is twice the height of the visible rect CGRect preheatRect = self.collectionView.bounds; preheatRect = CGRectInset(preheatRect, 0.0, -0.5 * CGRectGetHeight(preheatRect)); // If scrolled by a "reasonable" amount... CGFloat delta = ABS(CGRectGetMidY(preheatRect) - CGRectGetMidY(self.previousPreheatRect)); if (delta > CGRectGetHeight(self.collectionView.bounds) / 3.0) { // Compute the assets to start caching and to stop caching NSMutableArray *addedIndexPaths = [NSMutableArray array]; NSMutableArray *removedIndexPaths = [NSMutableArray array]; [self computeDifferenceBetweenRect:self.previousPreheatRect andRect:preheatRect addedHandler:^(CGRect addedRect) { NSArray *indexPaths = [self apple_indexPathsForElementsInRect:addedRect]; [addedIndexPaths addObjectsFromArray:indexPaths]; } removedHandler:^(CGRect removedRect) { NSArray *indexPaths = [self apple_indexPathsForElementsInRect:removedRect]; [removedIndexPaths addObjectsFromArray:indexPaths]; }]; NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths]; NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths]; CGSize itemSize = CGSizeMake((ScreenWidth-15)/3, (ScreenWidth-15)/3); CGSize targetSize = CGSizeScale(itemSize, self.traitCollection.displayScale); [self.imageManager startCachingImagesForAssets:assetsToStartCaching targetSize:targetSize contentMode:PHImageContentModeAspectFill options:nil]; [self.imageManager stopCachingImagesForAssets:assetsToStopCaching targetSize:targetSize contentMode:PHImageContentModeAspectFill options:nil]; self.previousPreheatRect = preheatRect; }}
- (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect addedHandler:(void (^)(CGRect addedRect))addedHandler removedHandler:(void (^)(CGRect removedRect))removedHandler{ if (CGRectIntersectsRect(newRect, oldRect)) { CGFloat oldMaxY = CGRectGetMaxY(oldRect); CGFloat oldMinY = CGRectGetMinY(oldRect); CGFloat newMaxY = CGRectGetMaxY(newRect); CGFloat newMinY = CGRectGetMinY(newRect); if (newMaxY > oldMaxY) { CGRect rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY)); addedHandler(rectToAdd); } if (oldMinY > newMinY) { CGRect rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY)); addedHandler(rectToAdd); } if (newMaxY < oldMaxY) { CGRect rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY)); removedHandler(rectToRemove); } if (oldMinY < newMinY) { CGRect rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY)); removedHandler(rectToRemove); } } else { addedHandler(newRect); removedHandler(oldRect); }}
- (NSArray *)apple_indexPathsForElementsInRect:(CGRect)rect{ NSArray *allLayoutAttributes = [self.collectionView.collectionViewLayout layoutAttributesForElementsInRect:rect]; if (allLayoutAttributes.count == 0) { return nil; } NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:allLayoutAttributes.count]; for (UICollectionViewLayoutAttributes *layoutAttributes in allLayoutAttributes) { NSIndexPath *indexPath = layoutAttributes.indexPath; [indexPaths addObject:indexPath]; } return indexPaths;}
- (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths{ if (indexPaths.count == 0) { return nil; } NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count]; for (NSIndexPath *indexPath in indexPaths) { if (indexPath.item < self.fetchResult.count && indexPath.item != 0) { PHAsset *asset = self.fetchResult[self.fetchResult.count-indexPath.item]; [assets addObject:asset]; } } return assets;}
END.
0 0
- PhotoKit相册的性能优化
- PhotoKit 监听相册变化
- iOS自定义相册性能优化
- 系统自带功能之相册(ALAssetLibrary)与最新的(PhotoKit)的使用
- 优雅的创建一个相册管理类(兼容AssetsLibrary和PhotoKit)
- 基于PhotoKit框架封装(相册的单选与多选)
- iOS PhotoKit获取所有相册名称
- iOS开发获取系统相册资源,自定义相册(PhotoKit)
- photokit
- iOS --- 使用PhotoKit代替ALAssetsLibrary来管理相册资源
- iOS-CollectionView自定义相册功能_性能优化
- iOS 使用photokit框架获取系统相册,实现多选,全选。
- ecshop优化17-图片相册相关的优化
- 【Android性能优化】布局的性能优化
- 性能优化,vewpage的优化
- Java 性能的优化
- Java性能的优化
- Java性能的优化
- SeaJS入门教程系列之使用SeaJS(二)
- 实现一个getMin功能的栈
- Android性能优化的方方面面
- Mac Karabiner 设置
- 【机房重构】七层登录
- PhotoKit相册的性能优化
- redis基础及特点
- win10开机黑时间数十秒原因及解决
- iOS coretext框架第二章 CTStringAttributes类介绍
- 程序员的沟通之痛
- Apache优化配置详解
- nodeJs知识点总结
- 【CodeForces506A】【DP】【记忆化搜索】Mr. Kitayuta, the Treasure Hunter 题解
- 管道流的简单应用