Bug 18415 - Attaching a gesture recognizer to a custom view causes leaks
Summary: Attaching a gesture recognizer to a custom view causes leaks
Status: CONFIRMED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll (show other bugs)
Version: 7.2.0
Hardware: PC Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-03-15 02:55 UTC by Adam Kemp
Modified: 2015-08-12 12:07 UTC (History)
6 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Example project (9.28 KB, application/zip)
2014-03-15 02:56 UTC, Adam Kemp
Details
Example project (9.27 KB, application/zip)
2014-03-15 16:26 UTC, Adam Kemp
Details

Description Adam Kemp 2014-03-15 02:55:59 UTC
This is yet another "circular references lead to leaks" situation, but it's one that is so easy to create that I feel like Xamarin really needs to do something about it. Here is the situation that leads to a leak (see the attached project for sample code):

1. You have a custom view (derives from UIView).
2. You attach a gesture recognizer to that custom view.
3. The handler for that gesture recognizer is either in another custom view class that is an ancestor of the custom view, or it is in a view controller whose view is an ancestor of the custom view.

The gesture recognizer is held in memory by the view, which is held in memory by the object with the handler, which is held in memory by the gesture recognizer.

The same thing would happen for any event on any custom view.

<rant>
I understand why this leaks, and I understand that it's a hard problem. I even have some idea of how to try to work around it. The problem is that this kind of behavior is totally antithetical to how iOS programming is supposed to work. Someone who is experienced in iOS programming, or even just learns how to do it from Apple's documentation or from other sources with an Objective C background are going to do things in a way that is almost guaranteed to leak memory like crazy. None of the examples I've seen on Xamarin's website or elsewhere even mention that this is a possible problem, let alone code it in a way that would avoid the issue (in fact, none of them I've seen use custom views, which sidesteps the problem entirely, but also sets people up for failure). For the plain event case (events on a custom view) I don't think I've seen any Xamarin examples that show the proper way to handle this to avoid leaks. The examples and documentation seem to just pretend this problem doesn't exist, which again just sets people up for failure. There have been numerous posts on the forums from people trying to figure out why things are leaking because it's so easy to do things wrong, and Xamarin doesn't show people how to do it right.

IMO, the difficulty of avoiding leaks in Xamarin.iOS is the biggest impediment to being successful with the product. Memory management in Objective C is relatively easy because of ARC, and it's relatively easy in C# because of the GC, but when the two are combined it is incredibly easy to introduce subtle leaks. And then to add insult to injury the only profiling tool available (HeapShot) is terrible. So not only are we pretty much guaranteed to get leaks in any non-trivial app, but diagnosing and fixing them is a slow and painful process. I love this product, but stuff like this is embarrassing.
</rant>
Comment 1 Adam Kemp 2014-03-15 02:56:29 UTC
Created attachment 6323 [details]
Example project
Comment 2 René Ruppert 2014-03-15 03:44:34 UTC
Something seems to be missing from your sample code. If I comment these lines in, it cannot find "leakTestView":

            // This wouldn't leak.
//            var gestureView = new UIView();
//            gestureView.AddSubview(leakTestView);
Comment 3 Adam Kemp 2014-03-15 16:26:06 UTC
Created attachment 6328 [details]
Example project
Comment 4 Adam Kemp 2014-03-15 16:28:00 UTC
Sorry, that code should read like this:

            // This wouldn't leak.
//            var gestureView = new UIView();
//            gestureView.AddSubview(new LeakTestView());

            // This does leak.
            var gestureView = new LeakTestView();

Those two commented out lines are meant to replace the last line quoted above to show that attaching the gesture recognizer to a stock UIView (with a custom view child) does not cause a leak, whereas attaching the gesture recognizer directly to the custom view does cause a leak.
Comment 5 Sadik Ali 2014-03-19 06:28:52 UTC
To check this issue I followed steps as mentioned in bug description and able to reproduce.

Steps:

1. Opened  attached project on XS and debug application with below code:
  var gestureView = new LeakTestView();
2. I noticed that LeakTestViewController and LeakTestView destructor is not called 
3. I commented code 
 var gestureView = new LeakTestView();

and uncommented code 

//            var gestureView = new UIView();
//            gestureView.AddSubview(new LeakTestView());

4. I noticed that in this case  LeakTestViewController and LeakTestView destructor is called.

Refer screen cast: http://screencast.com/t/X1saa3OM

Build Information:

=== Xamarin Studio ===
Version 4.2.3 (build 60)
Installation UUID: ce3f5199-e126-42fd-bc8a-6a96370af9ab
Runtime:
	Mono 3.4.0 ((no/6b959ef)
	GTK+ 2.24.23 theme: Raleigh
	GTK# (2.12.0.0)
	Package version: 304000151

=== Apple Developer Tools ===
Xcode 5.0 (3332.22)
Build 5A1412

=== Xamarin.Android ===
Version: 4.12.1 (Business Edition)

=== Xamarin.iOS ===
Version: 7.2.0.2 (Business Edition)

=== Build Information ===
Release ID: 402030060
Git revision: 30c4afc300c2a39ec5300851357ce02e49dd217e
Xamarin addins: f8a9589b57c2bfab2ccd73c880e7ad81e3ecf044

=== Operating System ===
Mac OS X 10.9.0
Darwin mac109s-Mac-mini.local 13.0.0 Darwin Kernel Version 13.0.0
    Thu Sep 19 22:22:27 PDT 2013
    root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64

Note You need to log in before you can comment on or make changes to this bug.