Я заметил что-то, что может повлиять на потребление памяти любой программы, и мне хотелось бы, чтобы некоторые мысли.События UIView и сбор мусора
Я создал очень простой тестовый проект с UIViewController и UINavigationViewController. Я нажимаю свой ViewController, а затем я его всплываю. GC выполняет эту работу, и мой ViewController освобождается (вызывается деструктор). Но, если я создаю UIButton, и я зарегистрировался на одно из его событий (например, TouchInsideUp), то мой ViewController не будет выпущен. Мне нужно незарегистрировать событие, чтобы выпустить мой ViewController. Чтобы быть уверенным, что это не проблема времени, у моего тестового приложения есть кнопка, которая вызывает GC.Collect().
Я не понимаю, что объект будет сохранен в живых, если он будет доступен из стека любого потока или статической переменной. Если мой ViewController имеет право на сбор мусора, тогда будет также UIButton. Событие не должно заставлять ViewController храниться в памяти, потому что UIButton недоступен GC. В моем случае ViewController используется только NavigationController, поэтому после его всплывания он всегда должен быть собран.
С помощью нового профилировщика (моно 2.10) я, может быть, найду логический ответ, но пока я озадачен. Есть идеи?
Отредактировано: Вот несколько кодов, которые помогут понять мой случай.
Мой тест ViewController довольно прост
public class TestViewController : UIViewController{
~TestViewController(){ Console.WriteLine("Finalizer called"); }
public UIButton Button {get; set;}
public override ViewDidLoad(){
base.ViewDidLoad();
// If I remove the event registering, my TestViewController is collected.
Button = new UIButton();
Button.TouchUpInside += ButtonTouchEventHandler;
View.AddSubview(Button);
}
void ButtonTouchEventHandler(object sender, EventArgs e){}
}
Мой MainWindow имеет NavigationController и выполняет следующие функции:
- Он толкнул новый экземпляр TestViewController (таким образом, только NavigationController имеет ссылку экземпляр TestViewController)
- TestViewController выталкивается через стандартную кнопку возврата (если я не регистрируюсь в TouchUpInside, вызывается финализатор TestViewController)
- Когда я возвращаюсь к MainWindow, кнопка позволяет мне позвонить GC.Collect, чтобы быть уверенным.
Его невозможно точно сказать, что происходит без видя ваше решение. –
Я добавил код и объяснение. Мне интересно, если под капотом регистрация событий связана с закрепленной памятью или статической переменной (в конечном итоге это событие связано с неуправляемыми ресурсами, поэтому, возможно, есть нечто большее, чем просто стандартное событие .Net). –
Спасибо, ваш код помог мне увидеть проблему. Был случай, когда это могло привести к тому, что граф объектов сохранится до отключения обработчика. Я исправил это в следующем моноточе. –