Примечание: Я создал простой проект - вы можете видеть, как изменяются типы переключения между
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);
}
Контроллер родительского представления просто представляет дочерний контроллер и устанавливает таймер, чтобы отменить его и запустить 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
достаточно, чтобы обмануть сборщика мусора в мозговой контроллер, который еще не имеет права на сбор.
Как это так?