MonoTouch/MT Garbage Collector: how to correctly r

2020-03-24 08:31发布

问题:

Have a look at the sample below which is not completely implemented but demonstrates what I'm talking about:

public class MyClass : UIView
{
  private UIView SubView;
  private UILabel ALabelInTheSubView;

  public override ViewDidLoad()
  {
  }

  // Imagine our view has a button. When clicked, a new sub view is added.
  public void HandleButtonAddView()
  {
    // Assign a new view to the SubView member and add a label.
    this.SubView = new UIView();
    this.ALabelInTheSubView = new UILabel("A label");
    this.SubView.AddSubView(this.ALabelInTheSubView);

    // Add the SubView to myself.
    this.AddSubView( this.SubView );
  }

  // Imagine our view has another button. When clicked, the sub view is removed.
  public void HandleButtonRemoveView()
  {
    this.SubView.RemoveFromSuperView();    
  }
}
  • If I click the button to add the subview, the member variables SubView and ALabelInTheSubView are assigned new instances of UIView and UILabel.
  • If I then click the button to remove the subview, SubView gets removed from super view.
  • After this.SubView.RemoveFromSuperView() the members SubView and ALabelInTheSubView still have references to the view or label, hence no memory will be released yet. Correct so far?
  • If I now click the button to add the sub view again, the members will be overwritten with NEW instances of UIView and UILabel.

QUESTION: Does the GC now know that it can now safely dispose the previously assigned UIView and UILabel? I mean, all references should be gone. Or do I have to call this.SubView.Dispose() and this.ALabelInTheSubView.Dispose() after removing from superview? And is disposing the label necessary at all, since it is a child node of the UIView, which just got removed and disposed (which would mean I always have to dispose from bottom to top)?

ADD. SIDE-QUESTION: If I call Dispose() on an object this IS still referenced - is that a a problem?

回答1:

The answer is yes, the garbage collector will now consider the two previous instances of the objects to not be reachable from anywhere, and will be collected the next time the GC runs.

You do not need to call Dispose() manually. The only reason to call Dispose() manually is in cases where you know that the object you are pointing to is some large object and you want to make sure that the memory is released immediately, and not wait for the GC to kick-in at some point in the future.

What happens when you call Dispose () on the object, is that we internally release the reference to the Objective-C object and we set the Handle property on the object to null. This means that if you try to call another method on a disposed object, you will get a nice exception.



回答2:

I would just reuse your SubView instead of making a new one each time. So create it in ViewDidLoad, store it in a member variable, and reuse it.

I don't think the extra memory will be a problem, and you won't have to worry about the GC at all.



标签: xamarin.ios