You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

选择照片后UIImagePickerController出现内存泄漏问题

解决UIImagePickerController内存泄漏的实用方案

巧了,我之前做项目也碰到过一模一样的问题!折腾了好几天才找到根源,其实UIImagePickerController的内存泄漏大多和代理引用逻辑、对象生命周期管理脱不了干系,给你几个针对性的排查和解决方向:

  • 检查代理的内存引用方式
    很多人踩坑是因为没注意代理的弱引用规则。不管是Swift还是OC,UIImagePickerController的delegate属性本身就是弱引用设计,但如果你在自己的控制器里强持有了picker实例,或者代理声明时不小心用了强引用,就会触发循环引用。

    举个Swift的正确写法:

    class YourVC: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        // 不需要强持有picker!用局部变量更安全
        func openPhotoPicker() {
            let picker = UIImagePickerController()
            picker.delegate = self
            picker.sourceType = .photoLibrary
            present(picker, animated: true)
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            // 处理图片逻辑
            if let selectedImage = info[.originalImage] as? UIImage {
                // 比如赋值给UI展示
                self.avatarImageView.image = selectedImage
            }
            // 直接dismiss,不用额外持有picker
            picker.dismiss(animated: true)
        }
    }
    

    如果是Objective-C,一定要把picker的属性声明为weak:

    @interface YourVC () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
    @property (nonatomic, weak) UIImagePickerController *imagePicker;
    @end
    
  • 避免不必要的强持有
    很多开发者习惯把picker实例存为控制器的强引用属性,但其实present之后系统已经持有了picker,完全可以用局部变量。dismiss后局部变量会被自动释放,从根源避免泄漏。如果必须存为属性,记得在dismiss完成后手动置空:

    picker.dismiss(animated: true) { [weak self] in
        self?.imagePicker = nil
    }
    
  • 排查图片处理环节的隐式引用
    有时候泄漏不是picker本身的问题,而是你在didFinishPickingMediaWithInfo里处理图片时,不小心用了强引用闭包。比如异步处理图片时,一定要用[weak self]打破循环:

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let image = info[.originalImage] as? UIImage else {
            picker.dismiss(animated: true)
            return
        }
        picker.dismiss(animated: true) { [weak self] in
            // 异步压缩图片等操作
            self?.compressAndSaveImage(image)
        }
    }
    
  • 考虑替换为更现代的PHPickerViewController
    如果你适配的是iOS 14及以上版本,完全可以用苹果推出的PHPickerViewController替代旧的UIImagePickerController。这个新框架不仅内存管理更稳定,还避免了很多旧框架的已知bug,用法也大同小异。

  • 用Leaks Instrument精准定位
    上面的方法都试了还没解决的话,直接用Xcode的Leaks工具排查。运行app后打开Instrument选择Leaks,操作一遍选图dismiss的流程,就能看到具体是哪个对象没被释放——如果是你的控制器实例没释放,那肯定是循环引用;如果是picker本身没释放,就找哪里还在强持有它。

我之前就是因为强持有了picker实例又没及时置空导致的泄漏,按照上面的方法调整后就解决了,你可以逐个排查试试。

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:12:39