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`?