注意:我创建了一个简单的项目——你可以看到在 storyboard 之间
UIButton
和里面切换类型是如何CustomButton
改变 GC 行为的。
我正试图让我的头脑围绕 MonoTouch 垃圾收集器。
该问题类似于MT 4.0 中修复的问题,但具有继承的类型。
为了说明这一点,考虑两个视图控制器,父级和子级。
子视图包含一个UIButton
在点击时写入控制台的单一视图。
Controller 的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);
}
父视图控制器只是呈现子控制器并设置一个计时器来关闭它并运行 GC:
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
为足以欺骗垃圾收集器认为子控制器尚不符合收集条件。
怎么会这样?