首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS Controller pop 後內存不釋放?ARC 引用計數與釋放時機深度解析

     編輯:程式設計綜合問答

現象描述

NavigationController pop ViewController 後,dealloc 不調用,Instruments 顯示內存持續增長,手動置 tableView = nil 才觸發釋放。

核心誤區:ARC ≠ 即時釋放

ARC(自動引用計數)在編譯期插入 retain/release,運行時當對象引用計數歸零時立即調用 dealloc。但「引用計數歸零」的時機取決於所有強引用持有者是否釋放,而非 pop 動作本身。

常見導致引用計數不歸零的原因

  1. Delegate/DataSource 循環引用:tableView.delegate = self 未聲明 weak。
  2. Block 循環引用:網絡回調、定時器、通知監聽捕獲 self 未用 __weak。
  3. 父視圖持有:view.addSubview(childVC.view) 但未調用 removeFromParentViewController。
  4. 單例/緩存持有:圖片緩存、數據管理器強引用 Controller。
  5. NSTimer 未失效:[timer invalidate] 缺失。

調試定位步驟

  1. Xcode → Debug Memory Graph (⌘⇧M) → 暫停運行 → 搜索 Controller 類名 → 查看紅色箭頭指向的強引用鏈。
  2. Instruments → Leaks + Allocations → 記錄 pop 前後 → 篩選該類對象 → 查看引用樹。
  3. 在 dealloc 打斷點/日誌確認是否真正未調用(Instruments 附加可能延遲釋放,以 Memory Graph 為準)。

修復清單

  • 所有 delegate/dataSource 屬性聲明 @property (weak) id delegate;。
  • Block 統一用 __weak typeof(self) weakSelf = self; 並在 Block 內 strongSelf 判空。
  • viewWillDisappear / dealloc 中:[timer invalidate]; [[NSNotificationCenter defaultCenter] removeObserver:self];。
  • 子控制器嵌入必須遵循:[self addChildViewController:vc]; [self.view addSubview:vc.view]; [vc didMoveToParentViewController:self]; 移除時對稱調用 willMoveToParentViewController:nil / removeFromParentViewController / removeFromSuperview。

關於「模擬器 dealloc 執行,Instruments 不執行」

Instruments 注入監測代碼會改變對象釋放時序,且 dealloc 可能在下一個 RunLoop 觸發。以 Memory Graph 顯示對象無強引用為準,即屬正常釋放。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved