Does calling ReleaseDesignerOutlets have any effect on MonoTouch GC?

garbage-collection, ios, memory-management, xamarin.ios

Solution

You should just call `Dispose()` on your controller when it is dismissed.

So something like:

private YourModalController modalController;

//When your button is clicked
partial void YourButtonClick() {
  modalController = new YourModalController();
  PresentViewController(modalController, true, delegate {
    modalController.Dispose();
    modalController = null;
  });
}

In `YourModalController`, make sure you have:

public override void Dispose(bool disposing) {
  ReleaseDesignerOutlets();
  base.Dispose(disposing);
}

You don't necessarily have to worry about `ViewDidUnload` in this case, since this controller is disposed when dismissed.

Prior to iOS 6:

- `ViewDidUnload` was called in a low memory warning for the app

- on controllers that are still in memory, but not actively on the screen such as down the stack in a `UINavigationController`

- On this event, you should dispose any views you have C# references to and set them to null

- for iOS 6 this doesn't happen any more

Likewise if you have this:

private UIButton buttonIMadeFromCode;

You should check for null, dispose it, and set it to null in `Dispose()` and `ViewDidUnload()` (but only mess with `ViewDidUnload` if you are targeting less than iOS 6).

Problem

The application I'm writing needs to support iOS5+. Recently, Apple obsoleted `ViewDidUnload` as we're told there is no significant memory gain in releasing views on memory warning. In my application, I have a `UIViewController` that manages a very heavy `UIWebView`. This view controller is presented modally and, as a result, often being created and dismissed. By using Instruments, I found out that the memory taken by `UIWebView` is not being freed immediately after its controller is dismissed. I assumed that the controller would eventually get collected by Mono GC, and it would call `Dispose` on the controller, as well as on its view, which would dispose `UIWebView` and free underlying native object. I can't test if this is the case: unfortunately after presenting and dismissing the controller for about ten times, I get a memory warning and the app crashes the next second. I'm not sure if Mono GC gets a chance to run at all. So what I did was adding `GC.Collect` call right after the controller has been dismissed. I also had to add `ReleaseDesignerOutlets` in `ViewDidDisappear`. This seems to free `UIWebView`. Update: I already found out that `ReleaseDesignerOutlets` call in `ViewDidDisappear` was obviously releasing the web view, but there was no benefit to GC call. In fact, GC never collected my controller because a button click handler was keeping the whole controller alive. Now, I feel completely lost in some kind of Cargo memory management. - Is it reasonably to force garbage collection in my case? - Why do I have to call `ReleaseDesignerOutlets`? Surely, if there are no references to the “dead” controller, its views should be considered eligible for collection as well? - From Instruments heapshot diff, it looks like the views created from code “hold on” to the controller as well. Do I have to dispose them? Nullify them? - Do I need to manually call `Dispose` on the controller I just dismissed? - Do I need to include `ReleaseDesignerOutlets` call in `Dispose` method of my controller? - Do I need to null out references to child views in my custom `UIView` subclasses on `Dispose`?

Original source

Related problems