1.图片选择
随着项目越来越大,图片视频选择样式越来越丰富,后期维护成本越来越高。项目初期所有的图片视频选择放在一个 viewController看着还挺满意,毕竟样式单一,逻辑还算清晰。可是后面样式越来越多,每次处理这部分代码,都要花费大半天时间来理解之前的逻辑。如果某一处逻辑考虑不全面,就会引出crash,所以每次迭代又要调整这部分代码时候,都是小心翼翼,严重影响项目进度。
终于在一次迭代中, PM提出图片选择增加集合的概念,便于几十屏照片的手机用户快速找到需要的图片。这次不能再往视频图片选择里面添加代码了,必须进行重构。
重构前一个MYImagePickerViewController里面码完所有代码。
重构后框架如下:
MYImageAssetManager:单例,实现相册集合数据源逻辑。初始化时,更新相册集合和相册中照片和视频的张数,且监听系统相册中资源更新。
MYMediaPickerViewController:父类,处理公共逻辑。1.请求访问授权 ;2.通过对应的PHAssetCollection获取图片视频展示;3.处理图片上下滑动缓存逻辑。
MYVideoPickerViewController:子类,处理视频选择逻辑。视频最小长度,拍照入口等等。
MYImagePickerViewController:子类,处理图片选择逻辑。单选、多选,选折后裁剪等等。
MYImageAlbumsViewController:顶部图片选择集切换。当MYImagePickerViewController进行图片集切换时,添加到父控制器MYImagePickerViewController上。
MYImageVideoPickerViewController:发图片发视频切换,如上图界面。在子控制器,MYImagePickerViewController和MYVideoPickerViewController之间切换。
下面分析MYImageAssetManager中部分代码:
.h文件中的供外界访问的属性和方法
videoAssetCollection是MYVideoPickerViewController控制器的视频集合。 imageDefaultCollection是MYImagePickerViewController控制器默认的图片集合。 imageAssetCollections是MYImageAlbumsViewController控制器的图片集数组。
2.图片选择内存占用高和界面上下滑动卡顿问题解决
图片选择多张大图时,很容易引发界面卡顿,内存占用率高,内存不足闪退等问题。
1>将获取原图方法- requestImageForAsset:targetSize:contentMode:options:resultHandler:修改为- requestImageDataForAsset:options:resultHandler:,在相同图片大小上,内存降低了很多。后者直接返回二进制数据,不渲染。
2>获取缩略图用- requestImageForAsset:targetSize:contentMode:options:resultHandler:,获取到UIImage后,可以用UIImageJPEGRepresentation转换为NSData,传递图像数据。UIImageJPEGRepresentation转化时候会有损耗,若项目中图片数据传递的较多,超过其带来的影响,所以可以忽略。
3>图片在传递中用NSdata,若要用到UIImage,就这样转换:[UIImage imageWithData:imageData]。
4>界面卡顿问题,可以将图片进行缓存, 用PHAsset的localIdentifier作为缓存的key。
下面两个方法分别用于获取缩略图和原图。
3.图片上传压缩,内存再次高占用闪退
图片压缩上传时,先获取原图,然后压缩。如果原图很大,压缩时内存再次高紧张。以下两个步骤可以解决此问题。
1>异步队列改为同步队列
图片压缩之前放在异步队列里面,当几十个图片并发压缩时,内存突然一下飙升,当所有图片压缩完成后,内存突然下降。就在突然飙升那一段,如果手机内存有限,应用就闪退了。之后改为同步队列,内存不会突然飙升,而是小幅上升依次处理每个压缩。代码如下:
这样子解决了部分问题,但是依然有闪退存在。
2>以“自动释放池”降低内存峰值
autoreleasepool自动释放池用于存放那些需要在稍后某个时刻释放的对象,清空自动释放池时,系统会向其中的对象发送release消息。创建自动释放池语法如下:
@autoreleasepool{... }
花括号定义了自动释放池的范围,自动释放池在左花括号处创建,并于右花括号处自动清空。位于自动释放池范围内的对象,将在此范围末尾处收到release消息。
因此,在压缩图像时,可以通过autoreleasepool控制应用的内存峰值,使其不致过高。