注:簡単なプロジェクトを作成しました
UIButton
。ストーリーボード間およびCustomButton
ストーリーボード内でタイプを切り替えると、GCの動作がどのように変化するかがわかります。
頭をMonoTouchガベージコレクターに巻き付けようとしています。
この問題はMT4.0で修正されたものと似ていますが、継承されたタイプがあります。
それを説明するために、親と子の2つのビューコントローラについて考えてみます。
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);
}
親ビューコントローラは、子コントローラを提示し、それを閉じて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
だけで、ガベージコレクターをだまして、子コントローラーがまだコレクションの対象ではないと考えさせることができます。
どうですか?