Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can identify strong reference cycles in Swift?

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.

like image 527
Itay Moav -Malimovka Avatar asked Aug 28 '15 01:08

Itay Moav -Malimovka


People also ask

What is strong reference cycle in Swift?

This can happen if two class instances hold a strong reference to each other, such that each instance keeps the other alive. This is known as a strong reference cycle. You resolve strong reference cycles by defining some of the relationships between classes as weak or unowned references instead of as strong references.

How can you avoid strong reference cycles in a closure?

A strong reference cycle happens when 2 instances keep a strong reference to each other. You can accidentally create such a cyclic reference, for example when working with 2-way “links” between objects, or with closures. You can break the cycle by marking a reference as weak, or by setting one of the references to nil.

What is a strong reference?

We have said that anytime a pointer variable points to an object, that object has an owner and will stay alive. This is known as a strong reference. A variable can optionally not take ownership of an object that it points to. A variable that does not take ownership of an object is known as a weak reference.

What is difference between weak and strong in Swift?

For example, a strong reference keeps a firm hold on instances and doesn't allow deallocation by ARC. Similarly, a weak reference cannot protect the instances from being deallocated by ARC. Before you learn about strong and weak reference, make sure to understand how classes and objects work in Swift.


1 Answers

The method for finding strong reference cycles is the same in Swift as 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 (debug memory graph). 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 illustrate the strong reference cycles:

debug memory graph

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 backward 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 type of objects are not being released, use "record reference count" feature to determine 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 an 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.

like image 134
Rob Avatar answered Oct 12 '22 11:10

Rob