UIView события и сборка мусора - PullRequest
4 голосов
/ 05 февраля 2011

Я наблюдал что-то, что может повлиять на потребление памяти любой программой, и мне хотелось бы подумать.

Я создал очень простой тестовый проект с 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, и он делает следующее:

  1. Он выдвинул новый экземпляр TestViewController (таким образом, только NavigationController имеет ссылку на экземпляр TestViewController)
  2. TestViewController вызывается с помощью стандартной кнопки назад (если я не регистрируюсь в TouchUpInside, вызывается финализатор TestViewController)
  3. Когда я возвращаюсь в MainWindow, кнопка позволяет мне вызвать GC.Collect просто для уверенности.

1 Ответ

0 голосов
/ 08 февраля 2011

Да, существует возможность блокировки графа объектов в этом шаблоне, я исправил это в следующей основной версии MonoTouch (MonoTouch 4)

...