NSArray ведет себя странно с объектами, выходящими за пределы области видимости

У меня странные проблемы с NSArray, когда некоторые члены объектов в моем массиве выходят за рамки, но не другие:

У меня есть простой объект под названием Section. В нем 3 члена.

@interface Section : NSObject {
    NSNumber *section_Id;   
    NSNumber *routeId;
    NSString *startLocationName;
}
@property(nonatomic,retain)  NSNumber *section_Id;  
@property(nonatomic,retain)  NSNumber *routeId;
@property(nonatomic,retain)  NSString *startLocationName;
@end


@implementation Section

@synthesize section_Id; 
@synthesize routeId;
@synthesize startLocationName;

//Some static finder methods to get list of Sections from the db
+ (NSMutableArray *) findAllSections:{


- (void)dealloc {
    [section_Id release];
    [routeId release];
    [startLocationName release];

    [super dealloc];
}

@end

Я заполняю его из базы данных методом findAllSection

self.sections = [Section findAllSections];

В поиске всех разделов я создаю некоторые локальные переменные, заполняя их данными из БД.

NSNumber *secId = [NSNumber numberWithInt:id_section];
NSNumber *rteId = [NSNumber numberWithInt:id_route];
NSString *startName = @"";

Затем создайте новый раздел и сохраните данные этих локальных переменных в разделе.

Section *section = [[Section alloc] init];

section.section_Id = secId;
section.routeId = rteId;
section.startLocationName = startName;

Затем я добавляю раздел в массив

[sectionsArray addObject:section];

Затем очищаю, освобождая локальные переменные и секцию, которую я добавил в массив [secId release]; [свежий релиз]; [начало выпуска]; [locEnd_name выпуск];

[section release];

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

Метод возвращается, и я проверяю массив и наличие всех разделов. Кажется, я не могу копать дальше, чтобы увидеть значения объектов Section в массиве (возможно ли это)

Позже я пытаюсь получить один из разделов

Я получаю это из массива

Section  * section = [self.sections objectAtIndex:row];

Затем проверьте значение

NSLog(@" SECTION SELECTED:%@",section.section_Id);

Но вызов section.section_Id потерпел крах, так как section.section_Id выходит за рамки.

Я проверяю других членов этого объекта Section, и они в порядке. После некоторых проб и ошибок я обнаружил, что, закомментировав выпуск переменной-члена, объект в порядке.

//[secId release];
[rteId release];
[startName release];
[locEnd_name release];


[section release];

Мои вопросы:

Я хорошо убираюсь?

Должен ли я освободить объект, добавленный в массив, и локальную переменную в функции?

Мой Dealloc в порядке в Разделе?

Этот код выглядит нормально, и я должен искать проблему в другом месте?

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

Я могу прокомментировать релиз, но предпочел бы знать, почему это работает, и не следует ли мне этого делать. Единственное место, где secId высвобождается, — это Dealloc.


person brian.clear    schedule 25.03.2010    source источник


Ответы (3)


Поддержу (третье) предложение прочитать правила управления памятью.

Версия TL;DR — это все, что вы alloc и вызываете метод с init в имени метода, и вы несете ответственность за его выпуск. Например:

NSString *string = [[NSString alloc] initWithFormat:@"%@", someObject];

В этом случае вы должны отпустить string. Тем не мение:

NSString *string = [NSString stringWithFormat:@"%@", someObject];

Здесь string выпускается автоматически. Это в основном эквивалентно этому:

NSString *string = [[[NSString alloc] initWithFormat@"%@", someObject] autorelease];

... это означает, что в следующий раз через цикл событий (что означает, возможно, как только ваша функция вернется), система отправит вам сообщение release для вас. Apple называет это «удобными методами».

Если у вас есть что-то вроде этого:

NSString *string = @"foo";

Затем string указывает на экземпляр NSString, который создается средой выполнения при инициализации вашей программы и не выходит за пределы области видимости, пока ваша программа не завершится. Никогда не release их тоже.

Опять же, прочитайте рекомендации и добавьте их в закладки. Но это должно ответить на ваш прямой вопрос.

person Frank Schmitt    schedule 25.03.2010
comment
Всем привет. //TODO: пятница - R.T.F.M. (Прочитайте руководство Feckin) или это должно быть R.T.F.MMM (прочитайте руководство Feckin Mem. Mgt.);) - person brian.clear; 26.03.2010

Вы не должны выпускать secId, rteId или startName. secId и rteId являются указателями на NSNumber экземпляров, созданных с помощью фабричного метода, который возвращает уже автоматически выпущенный объект. Статические строки (например, @"") освобождать не нужно. Вам необходимо перечитать Руководство по программированию управления памятью< /а>. Тогда прочитайте еще раз ;-) Это будет ваш друг.

person Barry Wark    schedule 25.03.2010
comment
@Барри тоже побил меня. Но он прав. За некоторыми исключениями вы освобождаете только объекты, созданные методами init, copy или new. - person kubi; 25.03.2010
comment
Я бы порекомендовал относиться ко всему, что кто-либо на SO говорит вам об управлении памятью, очень легко. Соблюдайте правила управления памятью, связанные с Барри. Люди склонны переформулировать их неформально и часто говорят это немного неправильно. Например, kubi просто пропустил copy и mutableCopy. Так что не слишком полагайтесь на переформулировку правил. - person Chuck; 25.03.2010
comment
Барри прав, но просто чтобы уточнить, вы не должны выпускать локальные NSNumber экземпляры, которые вы создаете. Вы все равно должны освободить переменные экземпляра. Как правило, вы можете сделать это более стильно, назначив nil свойству (self.section_Id = nil;) вместо вызова release в переменной экземпляра. - person warrenm; 25.03.2010
comment
@warrenm, пожалуйста, не назначайте nil свойству, чтобы освободить переменную экземпляра в вашем десструкторе. Если вы когда-нибудь добавите побочные эффекты в свой установщик свойств, это будет рецептом боли. Стандартной практикой является использование необработанных переменных экземпляра в методах init и dealloc и доступ к свойствам везде. - person Barry Wark; 26.03.2010
comment
Я с уважением не согласен, если вы не используете KVO. В любой другой ситуации, и особенно если вы добавляете настраиваемое поведение в мутатор, вы должны перепроверить, как вы выполняете окончательный выпуск, и в этом случае вы можете изменить его по мере необходимости. В противном случае нет причин осуждать этот выбор из соображений стиля. - person warrenm; 26.03.2010
comment
@warrenm Objective-C - это не C ++, где деструкторы вызываются автоматически (и соответствующим образом) для иерархий классов. Вот почему вы должны явно вызывать [super dealloc] в методе подкласса -dealloc. В этом случае суперкласс не может знать, изменил ли подкласс (или категорию) поведение мутатора. @bbum и другие разработчики Apple регулярно предлагают использовать прямой доступ к переменным экземпляра в -dealloc (фактически, это основная причина, по которой доступ к @synthesized переменным экземпляра был добавлен в последней среде выполнения). - person Barry Wark; 26.03.2010
comment
@warrenm Просто чтобы уточнить, я не рекомендую прямой доступ вместо доступа к свойствам везде, только в -init.. и -dealloc. - person Barry Wark; 26.03.2010
comment
@Barry_Wark Понятно. Я думаю, что ваше объяснение говорит в пользу вызова release внутри dealloc. - person warrenm; 29.03.2010

Вы выпускаете объекты, которые вам не принадлежат. Вам следует прочитать правила управления памятью.

person Chuck    schedule 25.03.2010