Как iOS решает, какие объекты будут отправлены? - PullRequest
3 голосов
/ 18 июня 2011

Я работаю над приложением для iPhone, в котором ряд UIViews динамически добавляются и удаляются из основного окна UIWindow.

При моделировании ошибок нехватки памяти в симуляторе я обнаружил, что не все контроллеры представления получают уведомление didReceiveMemoryWarning. К сожалению, это контроллеры, которые больше всего выиграют от реализации этого метода.

Я не могу найти хорошую информацию о том, где и как вызывается метод. Я прочитал упоминания о том, что он отправляется «всем UIViewControllers», но это, очевидно, не тот случай. Добавление точки останова в один из классов, которые получают уведомление, также не особо показательно.

Это сложный проект, но одним из способов добавления этих представлений является:

- (void) showMyView
{
  if(!myViewController){
    myViewController = [[MyViewController alloc]init];
    [window addSubview:myViewController.view];
  }
}

MyViewController - это подкласс другого класса, MySuperViewController, который сам является подклассом UIViewController. Ни у одного из этих классов нет соответствующих NIB; иерархии представлений создаются программно.

Я ищу указатели на то, как можно диагностировать проблему.

Ответы [ 4 ]

3 голосов
/ 18 июня 2011

Когда вы используете .view контроллера представления напрямую, есть большая вероятность, что ваш контроллер представления не получит много уведомлений, потому что это не правильный способ использования контроллера представления. UIWindow является особым случаем, потому что окно может автоматически знать контроллер вида и правильно направлять сообщение на контроллер.

Однако, когда вы отключаете представление от UIWindow, контроллер представления также отключается и больше не управляется UIWindow. Я думаю, что это источник проблемы.

Я бы предложил добавить контроллер навигации или контроллер панели вкладок в качестве корневого контроллера представления и использовать эту функцию контроллера представления для переключения между дочерними контроллерами. Обратите внимание, что вам не следует удалять контроллеры вида при переключении, чтобы они могли получать сообщения соответствующим образом.

Вы можете также рассмотреть возможность освобождения контроллера вида, если он не используется, если инициализация контроллера вида является тривиальной и не занимает слишком много времени.

2 голосов
/ 18 июня 2011

Где-то в вашем коде вы, вероятно, делаете что-то вроде этого:

[[NSNotificationCenter defaultCenter] removeObserver:self];

Единственное безопасное место для этого - -dealloc.

Везде, где вы должны указатьуведомление, для которого вы хотите отменить регистрацию (оно все равно может прерваться, если вы зарегистрируетесь для того же уведомления, что и суперкласс).

1 голос
/ 16 декабря 2014

Я ввел этот вопрос в поисках подходящего наблюдателя, имеющего дело с предупреждениями из памяти. Для тех, кто использует swift, вы можете зарегистрироваться следующим образом:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReceiveMemoryWarning:", name:UIApplicationDidReceiveMemoryWarningNotification, object: nil)

С методом обратного вызова:

func didReceiveMemoryWarning(notification: NSNotification){
    //Action take on Notification
}

Также убедитесь, что ваш пользовательский класс наследуется от NSObject, иначе вы получите эту ошибку:

… does not implement methodSignatureForSelector: — trouble ahead
1 голос
/ 18 июня 2011

Из документации

Реализация по умолчанию [didReceiveMemoryWarning] проверяет, может ли контроллер представления безопасно освободить свое представление.Это возможно, если само представление не имеет суперпредставления и может быть перезагружено либо из файла nib, либо с помощью пользовательского метода loadView.

Этометод вызывается, когда предупреждение о памяти "происходит" / моделируется.Когда памяти мало, система, вероятно, отправляет уведомление , и контроллер представления отвечает на уведомление, вызывая didReceiveMemoryWarning.

Если вы не переопределите метод, вызывается реализация по умолчанию (описанная выше). Все контроллеры представления в памяти получают предупреждение памяти и вызывают этот метод.Они просто ничего не делают, если небезопасно выпускать представление.

В простом тестовом приложении с контроллером навигации, как в текущем, так и в ранее отображаемом контроллере, didReceiveMemoryWarningназывается.Я не знаю, как именно работает NSNotificationCenter, но он знает, кто зарегистрировался для UIApplicationDidReceiveMemoryWarningNotification.Вероятно, он настроен примерно так:

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(didReceiveMemoryWarning)
                                             name:UIApplicationDidReceiveMemoryWarningNotification  
                                           object:nil];

Для получения дополнительной информации вы можете посмотреть раздел управления памятью в Справочник по классам UIViewController .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...