
DoImagePickerController 细节深挖RunLoop同步取图、前台自动刷新与内存清理的3处关键设计【免费下载链接】DoImagePickerControllerAn image picker controller with single selection and multiple selection. Support to select lots photos with panning gesture.项目地址: https://gitcode.com/gh_mirrors/do/DoImagePickerControllerDoImagePickerController 是一款轻量级 iOS 图片选择器控件支持单选与多选还能通过横滑手势一次性框选多张照片。本文面向 iOS 开发者带你深挖它源码中的 3 处关键设计RunLoop 同步取图、回前台自动刷新相册与用完即弃的内存清理这些细节正是此类控件在真机上表现稳定的核心原因。控件长什么样功能一览在深入源码前先看看这个控件能做什么详见 README.md 列数可调2、3、4 列网格布局️ 横滑多选按住滑动即可连续选中照片️ 长按预览0.3 秒长按弹出大图拖拽关闭 相册切换底部菜单可切换相册侧边按钮可直达顶部/底部 支持横屏模式整个控件的核心代码只有两个类负责相册数据源的单例 AssetHelper 和负责界面交互的 DoImagePickerController。下面逐一拆解 3 处最值得学习的设计。一、RunLoop 同步取图让异步 API 像同步方法一样好用iOS 的ALAssetsLibrary取图接口天然是异步的回调式但视图刷新、结果回传往往希望现在就拿到图片。AssetHelper在 getCroppedImage: 中给出了一个经典解法用 RunLoop 把当前线程挂住直到回调完成。核心套路只有三步定义__block BOOL bBusy YES;标记取图未完成在resultBlock回调末尾将bBusy NO;调用异步取图接口后用while (bBusy)循环驱动当前 RunLoop 持续运行直到标志翻转为NO才返回UIImage。while (bBusy) [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];这个写法让调用方可以像调用普通方法一样直接拿到图片对象彻底回避了回调嵌套。更贴心的细节是对于用户用系统相机编辑过的照片它会读取AdjustmentXMP元数据AssetHelper.m通过CIFilter还原出编辑后的真实画面而不是原始底片——很多第三方选择器在这里都会翻车。同文件中的 getImageFromAsset:type: 则按 4 种尺寸档位缩略图、宽高比缩略图、屏幕尺寸、原图分级取图网格页用缩略图、预览和导出才用大图从源头上控制内存占用。二、前台自动刷新一条通知解决照片过期问题用户打开选择器后可能切出去拍照、删图再回来相册内容其实已经变了。DoImagePickerController 的解法非常直接——在 viewDidLoad 中监听系统通知UIApplicationWillEnterForegroundNotification应用回到前台的瞬间触发 readAlbumList: 重新拉取相册列表并刷新界面。两个配套的细节体现了严谨性成对管理观察者viewDidDisappear: 中removeObserver移除监听避免控件销毁后收到野消息新照片置顶viewDidLoad里设置ASSETHELPER.bReverse YESDoImagePickerController.m 中 AssetHelper.m 会在枚举结束后反转数组保证刚拍的照片出现在最前面符合用户直觉。这种进入前台 → 全量重读相册的策略比手动刷新按钮的交互成本低得多用户完全无感。三、内存清理分清谁持有数据谁负责释放选择几百张照片时如果ALAsset数组一直挂在单例上内存会悄悄膨胀。项目用两种策略清理结果模式清理时机清理方DO_PICKER_RESULT_UIIMAGE默认控件消失时立即清空控件自己DO_PICKER_RESULT_ASSET调用方使用完毕后清空业务代码具体实现控件自动清理viewDidDisappear:中判断若为 UIImage 模式就调用 clearData把单例里的_assetGroups、_assetPhotos直接置nil——此时图片早已转成UIImage交给回调方asset 列表已无价值调用方手动清理ASSET 模式下回调拿到的ALAsset还依赖单例内部数据所以由业务代码负责。官方示例 ViewController.m 展示了标准姿势先把 asset 转成图片再[ASSETHELPER clearData]。模式常量定义在 DoImagePickerController.hDO_NO_LIMIT_SELECT表示不限张数此时官方建议改用 ASSET 模式以控制内存见 ViewController.m 的注释。顺带一提AssetHelper 单例的两个小心思延迟单例sharedAssetHelper 用dispatch_once保证全局唯一首次访问才创建ALAssetsLibrary不占用启动时间权限申请initAsset 通过向保存相册写一张nil图片的方式触发系统权限弹窗一行代码搞定 iOS 7 的相册授权。快速上手5 行代码接入DoImagePickerController *cont [[DoImagePickerController alloc] initWithNibName:DoImagePickerController bundle:nil]; cont.delegate self; cont.nMaxCount 4; // 最多选 4 张-1 为不限 cont.nColumnCount 3; // 2 / 3 / 4 列 [self presentViewController:cont animated:YES completion:nil];完整的接入示例可参考演示工程 ViewController.m 与界面骨架 DoImagePickerController.xib。总结DoImagePickerController 的体积虽小却把三个高频痛点都解决了RunLoop 自旋实现同步取图让异步 API 用得像同步方法前台通知自动刷新让相册永远最新分模式内存清理让多选几百张照片也不卡。这些设计对任何自研相册选择器、照片墙组件都有很强的借鉴价值。【免费下载链接】DoImagePickerControllerAn image picker controller with single selection and multiple selection. Support to select lots photos with panning gesture.项目地址: https://gitcode.com/gh_mirrors/do/DoImagePickerController创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考