Memory Management Pitfalls in Xamarin iOS - Pitfall 1
June 17, 2013
Pitfall #1 – Cyclical references in Parent/Child relationships
In the Introduction to this series, we talked about the interaction between Xamarin.iOS and the native Objective C iOS code. We pointed out that since Objective C is reference counted, the Xamarin.iOS C# garbage collector may have trouble releasing objects in certain scenarios and needs our help. Let’s look at one of those scenarios now.
This one if fairly easy to understand when you think about it. Suppose you create a custom UIView that accepts a reference to the parent view controller, like so:
public partial class MyView : UIView
public MyView (UIViewController parent)
this.parent = parent;
Creating and adding this view to your controller’s view hierarchy would create an indirect cyclical reference, since the controller points to the view (via its view hierarchy), and the view points to the controller via its “parent” variable. What we end up with is a cycle of references that can be seen in the following diagram:
The garbage collector won’t be able to correctly clean up these objects as we have a two-way dependency chain with the objects pointing to each other. We’ll have to ‘break’ one of these links in order to signal the garbage collector (GC) that it’s safe to get rid of the objects.
There are a few options to do this:
- Call .Dispose() explicitly on the controller
- Set the .parent variable to null
- Use the WeakReference class for the reference to the parent controller instead
None of those options are incredibly attractive when it comes down to it. What we normally try to do is avoid the situation completely and architect the classes a different way. This is one example of a cyclical reference that is fairly easy to avoid in the first place. Although you see examples around the Internet with code similar to this, there are other ways to go about it.