How can identify strong reference cycles in Swift?

匆匆过客 提交于 2021-02-05 12:48:10

问题


Is there a tool or method to locate strong references cycles in my SWIFT code?

A strong reference cycle is when two instances of classes reference each other without the proper safeties (weak/unowned) hence preventing the garbage collector from disposing of them once all the variables I created stopped referencing those objects.


回答1:


The method for finding strong reference cycles is the same in Swift as it is in Objective-C.

You'd run the app from Xcode, exercise the app sufficiently to manifest the cycle, and then tap on the "debug memory graph" button (). You can then select an unreleased object in the panel on the left and it will show you the memory graph, often which can clearly strong reference cycles:

Sometimes the memory cycles are not as obvious as that, but you can at least see what object is keeping a strong reference to the object in question. If necessary, you can then track backwards and identify what's keeping a strong reference to that, and so on.

Sometimes knowing what sort of object is keeping the strong reference is insufficient, and you really want to know where in your code that strong reference was established. The "malloc stack" option, as shown in https://stackoverflow.com/a/30993476/1271826, can be used to identify what the call stack was when this strong reference was established (often letting you identify the precise line of code where these strong references were established). For more information, see WWDC 2016 video Visual Debugging with Xcode.

You can also use Instruments to identify leaked object. Just run the app through Instruments with the Allocations tool, repeatedly (not just once or twice) returning the app back to some steady state condition and if memory continues to go up, then you likely have a strong reference cycle. You can use the Allocations tool to identify what sort of objects are not being released, use "record reference count" feature to identify precisely where these strong references were established, etc.

See WWDC 2013 video Fixing Memory Issues and WWDC 2012 video iOS App Performance: Memory for introductions to identifying and resolving memory issues. The basic techniques proposed there are still applicable today (though the UI of Instruments tools has changed a bit ... if you want introduction to the slightly changed UI, see WWDC 2014 video Improving Your App with Instruments).

As an aside, "garbage collection" refers to a very different memory system and isn't applicable here.




回答2:


You can add deinit functions to your classes that will get called when your objects are deallocated.

If deinit isn't getting called, while your app is running, you can press the Debug Memory Graph button (circled below) and inspect what has a reference to what.

Use the dropdown menus at the top of the middle pane to toggle between classes and instances of classes.

If something is getting allocated over and over again without getting released you should see multiple instances, and you should be able to see via the directional graph if one of its children is holding a strong reference to its parent.




回答3:


Use instruments to check for leaks and memory loss. Use Mark Generation (Heapshot) in the Allocations instrument on Instruments.

For HowTo use Heapshot to find memory creap, see: bbum blog

Basically the method is to run Instruments allocate tool, take a heapshot, run an iteration of your code and take another heapshot repeating 3 or 4 times. This will indicate memory that is allocated and not released during the iterations.

To figure out the results disclose to see the individual allocations.

If you need to see where retains, releases and autoreleases occur for an object use instruments:

Run in instruments, in Allocations set "Record reference counts" on (For Xcode 5 and lower you have to stop recording to set the option). Cause the app to run, stop recording, drill down and you will be able to see where all retains, releases and autoreleases occurred.




回答4:


You can use Instruments to do that. As the last paragraph of this article states:

Once Instruments opens, you should start your application and do some interactions, specially in the areas or view controllers you want to test. Any detected leak will appear as a red line in the “Leaks” section. The assistant view includes an area where Instruments will show you the stack trace involved in the leak, giving you insights of where the problem could be and even allowing you to navigate directly to the offending code.




回答5:


very simple approach is to put a print in deinitialiser

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

ensure that you are seeing this line getting printed on the console. put deinit in all your viewcontrollers. in case if you were not able to see for particular viewcontroller, means that their is a reference cycle.possible causes are delegate being strong, closures capturing the self,timers not invaidated,etc.



来源:https://stackoverflow.com/questions/32262172/how-can-identify-strong-reference-cycles-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!