美文网首页
iOS 内存泄漏的元凶——循环引用

iOS 内存泄漏的元凶——循环引用

作者: 落夏简叶 | 来源:发表于2020-01-07 11:51 被阅读0次

    项目中使用MLeaksFinder原理请戳我)检测内存泄漏,十分方便和直观。会精确到某个VC,某个View。

    MLeaksFinder发现内存泄漏的弹窗

    内存泄漏大多由于循环引用,导致循环引用的几种类型:

    • Block (基本项目中这种情况是最多的)
    • delegate
    • Timer
    • Notification

    Block循环引用(最常见)

    • block 会被copy, 并retain block中引用的对象。为打破引用循环,用weak修饰引用的对象。
    • [weak self][weak cell] 之后guard let strongSelf = self else {return}strongSelf为什么不会造成引用循环。 因为strongSelf在block中声明,相当于一个临时变量,block执行完毕后,会被释放掉,不会循环引用。
    • demo
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "XXTestCell", for: indexPath) as! XXTestCell
            // 防止引用循环
            // 1. 重新获取一个局部cell
    //        cell.buttonCallBack = {
    //            let cell = tableView.cellForRow(at: indexPath) as? XXTestCell
    //            cell?.configureLabel(with: "110")
    //        }
            
            // 2.不用重新获取,[weak cell]方式。以前没用过,用了之后发现很好用(推荐这种)
            cell.buttonCallBack = { [weak cell] in
                cell?.configureLabel(with: "110")
            }
    
    // 3. 引用循环
            cell.buttonCallBack = {
                cell.configureLabel(with: "110")
            }
            
            return cell
        }
    

    delegate循环引用

    谨记用weak来修饰delegate一般不会有啥问题了

    Timer循环引用

    解除Timer循环引用请戳我

    Notification循环引用

    1. 一般平常注册通知这么写,没啥问题
    NotificationCenter.default.addObserver(self, selector: #selector(receivedRotation), name: UIDevice.orientationDidChangeNotification, object: nil)
    
    @objc func receivedRotation(){
    }
    
    1. 突然看到一位童鞋写了这样的代码,对,就是循环引用了。


      image.png
    2. 修改,闭包发生的内存泄漏最好解,一般用[weak self],即可打破循环引用:

    NotificationCenter.default.addObserver(forName: .userLoggedIn, object: nil, queue: OperationQueue.main) { [weak self] (noti) in
                self?.swiftTruckSettins(self?.avoidTollsSwitch)
    }
    
    1. 原因,先看此方法描述
    - (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
        // The return value is retained by the system, and should be held onto by the caller in
        // order to remove the observer with removeObserver: later, to stop observation.
    

    文档中明确说明了,调用者会持有返回的observer对象。 VC -> observer -> block, block -> VC。具体验证详情请戳我

    注:

    • MLeaksFinder检测textfiled会误判泄漏,其实没有哦。

    相关文章

      网友评论

          本文标题:iOS 内存泄漏的元凶——循环引用

          本文链接:https://www.haomeiwen.com/subject/tnmqactx.html