簡體   English   中英

如何識別 Swift 中的強引用循環?

[英]How can identify strong reference cycles in Swift?

是否有工具或方法可以在我的 SWIFT 代碼中定位強引用循環?

強引用循環是指類的兩個實例在沒有適當的安全性( weak / unowned )的情況下相互引用,因此一旦我創建的所有變量都停止引用這些對象,就會阻止垃圾收集器處理它們。

查找強引用循環的方法在Swift中與在Objective-C中相同。

您可以從Xcode運行應用程序,充分運行應用程序以顯示循環,然后點擊“調試內存圖”按鈕( 調試內存圖 )。 然后,您可以在左側面板中選擇未發布的對象,它將顯示內存圖,通常可以顯示強大的參考周期:

調試內存圖

有時候內存周期並不那么明顯,但你至少可以看到哪個對象保持對相關對象的強引用。 如有必要,您可以向后追蹤,並確定哪些內容對此有強烈的參考,等等。

有時知道什么類型的對象保留強引用是不夠的,並且您真的想知道代碼中的哪個位置建立了強引用。 “malloc stack”選項,如https://stackoverflow.com/a/30993476/1271826所示,可用於識別建立此強引用時的調用堆棧(通常可讓您識別准確的代碼行)這些強有力的參考建立的地方)。 有關更多信息,請參閱WWDC 2016視頻使用Xcode進行可視化調試

您還可以使用Instruments來識別泄漏的對象。 只需通過使用Allocations工具的應用程序運行應用程序,重復(不只是一次或兩次)將應用程序恢復到穩定狀態狀態,如果內存繼續增加,那么您可能會有一個強大的參考周期。 您可以使用“分配”工具來識別未發布的對象類型,使用“記錄引用計數”功能來准確識別這些強引用的建立位置等。

請參閱WWDC 2013視頻修復內存問題和WWDC 2012視頻iOS應用程序性能:內存,用於介紹識別和解決內存問題。 現在提出的基本技術仍然適用(盡管儀器工具的UI已經發生了一些變化......如果您想要了解稍微改變的UI,請參閱WWDC 2014視頻使用儀器改進您的應用程序 )。

另外,“垃圾收集”是指一種非常不同的存儲系統,在此不適用。

您可以將deinit函數添加到將在取消分配對象時調用的類。

如果沒有調用deinit,則在您的應用程序運行時,您可以按下Debug Memory Graph按鈕(在下面圈出)並檢查哪些內容有參考。

調試內存圖按鈕

使用中間窗格頂部的下拉菜單在類和類實例之間切換。

如果在沒有被釋放的情況下一次又一次地分配某些內容,您應該看到多個實例,並且您應該能夠通過方向圖看到其中一個子項是否持有對其父項的強引用。

使用儀器檢查泄漏和記憶喪失。 在儀器上的分配工具中使用標記生成(快照)。

有關如何使用快照查找內存褶皺,請參閱: bbum blog

基本上,該方法是運行Instruments分配工具,獲取快照,運行代碼的迭代並重復另外3到4次快照。 這將指示在迭代期間分配但未釋放的內存。

要弄清楚結果披露以查看個別分配。

如果您需要查看對象使用儀器的保留,釋放和自動釋放的位置:

在儀器中運行,在分配中設置“記錄參考計數”(對於Xcode 5及更低版本,您必須停止記錄以設置選項)。 導致應用程序運行,停止錄制,向下鑽取,您將能夠看到所有保留,釋放和自動釋放發生的位置。

您可以使用Instruments來做到這一點。 正如本文最后一段所述

儀器打開后,您應該啟動應用程序並進行一些交互,特別是在您要測試的區域或視圖控制器中。 任何檢測到的泄漏都會在“泄漏”部分顯示為紅線。 輔助視圖包括一個區域,儀器將向您顯示泄漏中涉及的堆棧跟蹤,讓您深入了解問題所在,甚至允許您直接導航到有問題的代碼。

非常簡單的方法是在deinitialiser中打印

deinit {
   print("<yourviewcontroller> destroyed.")
}

確保您在控制台上看到此行已打印。 把deinit放在你所有的viewcontrollers中。 如果您無法查看特定的viewcontroller,則意味着它們是一個引用循環。可能的原因是委托強,捕獲自我的閉包,未定時的定時器等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM