2012-06-18 4 views
2

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

FooterViewController В комплект поставки входит ярлык для показа обратной связи с пользователем. Я бы хотел, чтобы этот ярлык сохранялся до тех пор, пока мое значение не изменилось моим приложением. В нормальных условиях это происходит. Тем не менее, я только что начал тестирование с предупреждениями о памяти, и я обнаружил, что после того, как представление выгружено в ответ на предупреждение о памяти, метка очищается.

Вот что я пытался до сих пор, чтобы решить эту проблему: в viewWillUnload методе FooterViewController «s, хранить текст лейбла в переменной экземпляра под названием statusString:

- (void)viewWillUnload 
{ 
    statusString = [statusLabel text]; 
    testInt = 5; 
    NSLog(@"View will unload; status string = %@; testInt = %d", 
      statusString, testInt); 

    [super viewWillUnload]; 
} 

Следует отметить, что я также набор другая переменная экземпляра объявлена ​​NSInteger testInt, до 5.

Тогда, в FooterViewController «s viewDidLoad метод, я пытаюсь установить текст лейбла к statusString:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSLog(@"Just before setting label, statusString: %@; testInt: %d", 
      statusString, testInt); 
    [statusLabel setText:statusString]; 
    NSLog(@"View did load."); 
} 

Однако это не работает. Кроме того, в журнале после моделирования предупреждения памяти, я вижу:

View will unload; status string = Invalid IP address Error code: 113; testInt = 5 

(Обратите внимание, что «Неверный код IP-адрес ошибки: 113» правильное значение для statusString)

Затем, после навигации по FooterViewController опять же, я вижу:

Just before setting label, statusString: (null); testInt: 0 

Это указывает мне, что по какой-то причине, переменные экземпляра FooterViewController являются переинициализации, когда вид нагрузки снова. Последнее замечание: метод initWithNibName:bundle: вызывается каждый раз, когда представление должно перезагружаться, хотя я ожидаю этого; в конце концов, представление должно быть перезагружено из NIB.

Итак, мои вопросы таковы:

  1. Почему эти переменные экземпляра, по всей видимости аннулируются или обнуляется в процессе выгрузки и перегрузки вид?
  2. Если я делаю что-то неправильно, это вызывает эту аннулирование, что это такое?
  3. Если я не делаю что-либо неправильно, и это нормальное поведение, как я должен обрабатывать состояние состояния между загрузками представления?

Спасибо, Райли

ответ

0

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

Решение было перемещать [[FooterViewController alloc] init] к init методу FooterViewController «ы родительского VC, так что инициализация была выполнена только один раз за цикл выполнения.

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

Спасибо за помощь, которую я получил от двух ответчиков.

0

statusString выглядит как слабая ссылка, а не сильным свойством. Он не может сохранить текст ярлыков, который освобождается от ярлыка при разгрузке представления. Вот почему вы сначала получаете правильное значение (до того, как метка освобождена), и null позже (после того, как метка была освобождена, и слабая ref аннулирована). Превратите свой статусString в сильное свойство, и что магия ARC больше не кусает вас.

+0

Я объявил statusString как сильное свойство: '@property (неатомический, сильный) NSString * statusString;' и синтезировал его. Тем не менее, я все еще вижу ту же проблему. Я не уверен, что это именно то, что происходит. – ravron

+0

Теперь это странно. Я бы использовал явный setter self.statusString = statusLabel.text вместо прямого ivar-аффектации, просто чтобы увидеть, но я признаю, что сейчас озадачен. Если сеттер ничего не изменит, мы оба должны перечитать документацию ARC :-) –

+0

Согласовано. Я заключил в явный setter: 'self.statusString = [statusLabel text]' и все еще вижу одинаковые результаты. У меня создается впечатление, что предупреждения о памяти обычно освобождают вид VC, но не сам VC. Я обманул? – ravron

0

Похоже, что вам нужно использовать didRecieveMemoryWarning вместо viewDidUnload, поскольку viewDidUnload не может быть вызван в случае предупреждения о памяти. Если авария полностью завершена, вам необходимо записать данные на диск, используя что-то вроде coreData. Сохраните данные здесь, а затем вызовите супер, чтобы представление все равно было выпущено. Надеюсь, это поможет.

+0

Хм, хорошая мысль. Вы правы, что я должен использовать 'didReceiveMemoryWarning'. Однако это не корень моей проблемы. Спасибо за хедз-ап! – ravron

+0

Мне должно быть ясно, что я проверил это решение и не нашел его полезным. Кроме того, я нашел фактическую причину и решение моей проблемы и самостоятельно опубликую ее после 8-часового ожидания, которое SO требует от меня. Проклятие моей низкой репутации! – ravron