#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 для чего-то другого. Забыв об этом шаге, я искал сумасшедшие причины. Спасибо.