Источники данных табличного представления запущены дважды, проблема с областью действия

#iphone #objective-c #uitableview #scope

#iPhone #objective-c #uitableview #область действия

Вопрос:

У меня есть UITableView, где numberOfSectionsInTableView и numberOfRowsInSection вызываются дважды, при втором запуске возникают проблемы с областью действия. Если я замаскирую проблему, я получу проблему с областью действия при первом запуске cellForRowAtIndexPath.

Большая часть данных поступает из NSDictionary, который настраивается во время viewDidLoad. У меня также есть NSArray, настроенный одновременно. После установки они никогда не изменяются и не выпускаются.

Когда numberOfSectionsInTableView вызывается в первый раз, все в порядке. Подсчитывает элементы по мере необходимости и т.д. Затем он немедленно вызывается во второй раз (понятия не имею, почему). При втором запуске он не может получить доступ к элементам NSDictionary или NSArray. Сбой даже при попытке их NSLog. Например:

 NSLog(@"theMainDictionary %@",theMainDictionary);
  

обычно это приводит к EXC_BAD_ADDRESS, но иногда что-то вроде этого:

 theMainDictionary <_UITableViewSeparatorView: 0x4e73680; frame = (0 307; 320 1); opaque = NO; autoresize = W; layer = <CALayer: 0x4e4bf20>>
  

Опять же, эта же строка выполняется нормально (регистрируя словарь, как ожидалось) при первом запуске.

Если я замаскирую проблему, вернув фиксированный NSInteger, numberOfRowsInSection затем сделает то же самое. Если я замаскирую numberOfRowsInSection, cellForRowAtIndexPath завершится сбоем при первом запуске. Та же проблема — не удается получить доступ к theMainDictionary или связанному NSArray.

Я не могу понять, почему они запускаются дважды — нигде нет reloadData. Я также не знаю, почему второй вызов выполняется по-другому. Любая помощь приветствуется.

Комментарии:

1. не могли бы вы показать код для всего файла .m?

Ответ №1:

Вероятно, вы создаете свой словарь с помощью [NSDictionary dictionary] или одного из нескольких похожих заводских методов (который возвращает автоматически выпущенный экземпляр), а затем сохраняете его непосредственно в ivar без сохранения. Это будет работать нормально, пока ваша программа не вернется к основному циклу выполнения, после чего авторелиз разрешится и объект будет освобожден.

Есть несколько способов это исправить:

  • Присваивается объявленному свойству retain , а не ivar. Это означает, self.theMainDictionary а не просто theMainDictionary . Это сохранит его для вас, поэтому оно будет сохраняться до тех пор, пока вы его не освободите (или не назначите свойству другой словарь или nil ).
  • Используйте [[NSDictionary alloc] init] (или один из многих других методов инициализации) вместо [NSDictionary dictionary] style. Это возвращает экземпляр, которым вы владеете, поэтому он будет оставаться до тех пор, пока вы его не освободите.
  • Явный вызов retain словаря при сохранении его в ivar. Это требует владения, поэтому оно будет действовать до тех пор, пока вы его не освободите.

Во всех случаях не забудьте освободить словарь в вашем dealloc методе, иначе произойдет утечка памяти.

Все вышесказанное, вероятно, относится и к массиву. Смотрите документацию Apple для более подробного объяснения управления памятью в Cocoa.

Комментарии:

1. Тьфу — не могу поверить, что я это пропустил. Первоначально это было свойство, затем измененное на ivar для чего-то другого. Забыв об этом шаге, я искал сумасшедшие причины. Спасибо.