Question

I stumbled about this question: Button in ContentView causes crash in MonoTouch runtime. Bug in Monotouch 4.0? and the inquirer has problems with Monotouch's "more aggressive" garbage collector.

  • Can somebody explain why in the inquirer's case the error is issued (what gets collected and why?)?
  • What does "more aggressive" mean? What are the traps I can fall into? What should I avoid?
  • With regards to iOS5: Apple claims with iOS5 the app will get one memory warning and then it will get killed. Unlike any other version before, where an app received three warnings. What does that mean for Monotouch? How will it deal with this behavior?

Maybe one of the Xamarin team can sum up some dos and don'ts and give a good explanation?

I am currently upgrading from MT 3.2.6 to MT 4.1 and would like to go through my code and check what has to be changed.

Was it helpful?

Solution

We found that sometimes developers would run into strange problems like dialogs would sometimes stay on the screen, and sometimes they would vanish without leaving a trace and with no explanation of why this happened.

This typically happened when you created an UIAlertView and kept no references to it, so as far as MonoTouch was concerned, that object was garbage (you did not reference it from your code, so you did not have a use for it).

But whether the dialog vanished from your screen immediately or later depended on whether the Garbage Collector's heuristics had determined that it was time to run a collection. If you had created a dialog just after a collection, chances are, your dialog would stay on the screen. But if you were very close to a collection, or if you had a background process consuming memory, then the GC would be triggered.

This in general was confusing to users, "why are things vanishing randomly". The answer was: if you did not keep a reference to it, the GC assumed you did not care.

To make this more clear to our users, when running MonoTouch on debug mode on the simulator (and there is a command line option to control that for any builds), we added a thread on the simulator that continuously calls GC.Collect() every few seconds. This makes it more obvious that you might have not kept a reference to a dialog of yours.

Later on, we found out that a very useful and common pattern was to keep two kinds of dialog boxes around that really have no use other than their side effects: UIAlertView and UIActionSheet. We altered MonoTouch so that it internally keeps references to those two until dismissed.

So we ended up with the best of both worlds: during the development cycle you catch earlier missing references to objects that you need, and we took care of the two most common cases that are only useful for their side effects.

OTHER TIPS

That's a lot of good questions.

About the aggressiveness, a Garbage Collector can collect objects once there are no more references to them. If it does this slowly (call this passive) you might never notice some bugs you have in your software.

OTOH running applications (multitasking) under low-memory condition brings it's own problems. So collecting more often (call this aggressive) will reclaim memory faster and can help overall performance. However you are more likely to hit (your own) bugs in cases where objects are still used after no managed references are held.

So after reading the code I could not find why this would be a problem (and there was not enough code to try it quickly). Now if the crash was related to UIButton then AddSubView should have logically made the reference. Reading the documentation confirmed that to be the case (emphasis is mine):

The view to be added. This view is retained by the receiver. After being added, this view appears on top of any other subviews.

A bit of googling got me to bug #670294 which links to a stackoverflow question very similar to the one you linked. Comment #22 describe a workaround for this issue (it's a bug) and is fixed in MonoTouch 4.1.

Right now I can't tell you it that's a GC issue affecting MonoTouch itself (same rules applies to everybody) or unrelated. I would guess it's related since keeping another reference was cited as the solution - but since I'm curious I'll look at the fix and add a comment later ;-)

I'm the one who said the GC was "more aggressive".. That's my term - I think Miguel views it a little differently. My interpretation was based on the fact that things you could get away with in MT3 no longer work (or are not as reliable) in MT4.

Another answer...

With regards to iOS5: Apple claims with iOS5 the app will get one memory warning and then it will get killed. Unlike any other version before, where an app received three warnings. What does that mean for Monotouch? How will it deal with this behavior?

I won't talk about iOS5 (since I don't track what's public and what's not). Since you cannot know how low memory could be (or required by something else) there's no point in having very complex strategy to free memory. The user needs it elsewhere, give it back :)

The way to deal with this is to override DidReceiveMemoryWarning and free everything you can, like:

  • call GC.Collect() - it's one of the few, right time to call this;
  • clear any cache(s) you have (e.g. downloaded data, anything else you can re-compute later if needed)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top