注意: 我制作了一个简单的项目,您可以查看在故事板中在
UIButton
和CustomButton
之间切换类型如何改变GC行为。
我试图理解MonoTouch垃圾收集器。
问题类似于MT 4.0中修复的问题,但是处理继承类型。
为了说明这一点,请考虑两个视图控制器,父级和子级。
子视图包含一个单独的UIButton
,点击时会向控制台输出内容。
控制器的Dispose
方法会抛出异常,因此很难错过。
以下是子视图控制器:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
sayHiButton.TouchUpInside += (sender, e) =>
SayHi();
}
}
void SayHi()
{
Console.WriteLine("Hi");
}
protected override void Dispose (bool disposing)
{
throw new Exception("Hey! I've just been collected.");
base.Dispose (disposing);
}
父视图控制器只是呈现子控制器并设置一个计时器来关闭它并运行垃圾回收:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var child = (ChildViewController)Storyboard.InstantiateViewController("ChildViewController");
NSTimer.CreateScheduledTimer(2, () => {
DismissViewController(false, null);
GC.Collect();
});
PresentViewController(child, false, null);
}
如果您运行此代码,则可以预测它会在ChildViewController.Dispose()
内崩溃,因为子控制器已被垃圾回收。很酷。
现在打开故事板并将按钮类型更改为CustomButton
。MonoDevelop将生成一个简单的UIButton
子类:
[Register ("CustomButton")]
public partial class CustomButton : UIButton
{
public CoolButton (IntPtr handle) : base (handle)
{
}
void ReleaseDesignerOutlets()
{
}
}
通过将按钮类型更改为 CustomButton
,可以欺骗垃圾收集器认为子控制器尚未符合收集条件。
为什么会这样呢?