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

iOS dealloc 不調用?循環引用與釋放時機深度解析

     編輯:程式設計綜合問答

現象描述

Controller 被 pop 後 dealloc 不打印,手動在 viewWillDisappear 置 tableView = nil 後反而觸發 dealloc。

根本原因:強引用循環

tableView 的 delegate/dataSource 通常設置為 self(Controller),且 tableView 被 view 強引用,形成:

Controller → view → tableView → delegate/dataSource → Controller

若 tableView 未從父視圖移除且未置 nil,引用計數永不歸零,ARC 不會調用 dealloc。

為什麼手動置 nil 有效?

_tableView = nil 切斷了 Controller → tableView 的強引用鏈,引用計數歸零,觸發 dealloc。

正確解決方案(不依賴手動置 nil)

  1. 弱引用 delegate:tableView.delegate = self 改為 weak 屬性(需自定義 UITableView 子類暴露 weak delegate)。
  2. 在 viewDidDisappear 移除:[self.tableView removeFromSuperview]; self.tableView = nil; —— 這是蘋果推薦的清理時機。
  3. 使用 UITableViewController:系統自動管理生命週期,pop 時自動釋放。
  4. 檢查 Block/閉包循環:網絡回調、定時器、通知監聽均需 weakSelf。

調試工具

  • Instruments → Leaks:運行並操作 pop,檢查是否有泄漏對象。
  • Debug Memory Graph (Xcode 10+):暫停運行,點擊圖標查看對象引用關係,紅色箭頭即循環引用。
  • FBRetainCycleDetector:自動掃描並上報循環引用。

關於「模擬器調用 dealloc,Instruments 不調用」

Instruments 附加進程會改變內存管理時機,且 dealloc 可能在下一個 RunLoop 才執行。以 Memory Graph 為準,若對象已無引用則屬正常釋放。

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