2009-03-25 3 views
2

Функции Я смотрю на:Присвоение значений переменным экземпляра в Objective C

-(void)viewDidLoad { 
    NSBundle *bundle = [NSBundle mainBundle]; 
    NSString *plistPath = [bundle pathForResource:@"statedictionary" ofType:@"plist"]; 

    NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath]; 
    self.statesZips = dictionary; 
    [dictionary release]; 

    NSArray *components = [self.stateZips allKeys]; 
    NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)]; 
    self.States = sorted; 

    NSString *selectedState = [self.states objectAtIndex:0]; 
    NSArray *array = [stateZips objectForKey: selectedState]; 
    self.zips = array; 
} 

Почему NSDictionary выделена, то присвоенного указатель называется * словарь, а затем присвоенного экземпляр переменной stateZips? Почему бы не выделить его и присвоить его непосредственно переменной экземпляра и сохранить память о создании и выпуске другого NSDictionary? Та же методология всегда следует, в том числе и в конце этой функции с NSArray ...

NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath]; 
self.statesZips = dictionary; 
[dictionary release]; 

Кроме того, эта сортировка ставит ключи из хэш-таблицы (словарь) в алфавитном порядке. Я не уверен, я понимаю эту строку:

NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)]; 

ответ

6

Никто не кажется, адресованный тот факт, что линия

self.statesZips = dictionary; 

не является непосредственно переменной присваивание экземпляра.stateZips - свойство, и поэтому строка кода вызывает метод setStateZips:. Этот метод сохраняет или копирует словарь, поэтому, если метод viewDidLoad не намерен использовать его для какой-либо цели, он больше не нужен. Это делает его ОК release.

предыдущая строка:

[[NSDictionary alloc] initWithContentsOfFile:plistPath]; 

выделяет объект. Это делает вашу ответственность за release, если вам это больше не нужно. После присвоения ему свойства statesZips он больше не нужен, поэтому он выпущен, и вы не должны использовать dictionary. Вы заметите, что более поздний код относится только к self.stateZips, а не к dictionary.

В случае NSArray в дальнейшем метод viewDidLoad не выделяет объект, поэтому метод не отвечает за вызов release. Эмпирическое правило состоит в том, что если вы его используете, вы несете ответственность за то, чтобы он был выпущен. В противном случае это не ваша проблема.

Сортировка массива использует метод sortedArrayUsingSelector:. Селектор идентифицирует метод в Objective-C. И @selector - это буквальный синтаксис для селекторов (вроде как @"" - это буквальный синтаксис для объектов NSString). Итак, что говорит этот код, «дайте мне массив, в котором объекты в components отсортированы и используют метод compare: для сравнения каждого объекта при сортировке. Когда он сортирует массив, он будет вызывать compare: на объектах в массив, чтобы определить, как их упорядочить.

+1

Я действительно считаю, что семантика сохранения/присваивания свойства statesZips не имеет значения. Код выделяет объект, поэтому ему необходимо его освободить, * независимо от * семантики состояний Zips, если только она не работает в среде, собранной для мусора. –

+0

@ Barry Wark: ну, нет. семантика состояний Zips очень важна. если этот метод не сохранит словарь или не скопирует его, доступ к состояниям Zip после строки 7 приведет к неопределенному поведению (вероятно, segfault). – hop

+0

Функции удобства, такие как initWithContentsOfFile, автореализовываются. –

4

statesZips Свойство, вероятно, сохраняется, это рассуждение.

Когда NSDictionary сначала выделяется, его счетчик сохранения равен 1. Когда он присваивается состояниям Zips, счетчик удержания становится равным 2. Когда он отпущен, количество удержания падает до 1, что обычно является желаемым результатом.

Обратите внимание, что код ниже произвел бы (почти) тот же результат:

self.statesZips = [NSDictionary dictionaryWithContentsOfFile:plistPath]; 

, потому что dictionaryWithContentsOfFile возвращает объект autoreleased.

Как правило, методы класса, такие как [NSDictionary dictionary], возвращают автореализованные объекты (которые автоматически освобождаются через некоторое время), в то время как обычный метод alloc-init (как в [[NSDictionary alloc] init]) возвращает сохраненные объекты.

Я предлагаю вам прочитать Memory Management Programming Guide for Cocoa для получения дополнительной информации.

EDIT: Я, должно быть, пропустил последнюю часть вашего вопроса, когда впервые прочитал ее, но Барри уже ответил на эту часть.

2

В этом коде используется управление памятью с подсчетом отсчетов (а не автоматическое управление памятью мусора, доступное в Objective-C 2.0 на OS X). Когда любой объект (в данном случае NSDictionary и NSArray) являются alloc'd, вызывающий отвечает за вызов -release на этом экземпляре. Неспособность вызвать выпуск вызывает утечку памяти. Код может быть записана в виде

self.statesZips = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] autorelease]; 

, но за счет более явного управления памятью (опирающейся на NSAutoreleasePool освободить alloc'd экземпляр в конце итерации цикла обработки событий.

вызов

[components sortedArrayUsingSelector:@selector(compare:)]; 

возвращает массив, элементы которого происходит из components, но в соответствии с возвращаемым значением вызова [elem1 сравнение: elem2]. для сравнения двух элементов массива

+0

+1 для фактического правильного ответа на вопрос, заданный. Семантика свойства statesZip здесь не имеет значения. Причиной шаблона является четкость кода и явное управление памятью как вы сказали.Спасибо Apple за ARC, чтобы мы получили все меньше и меньше этих вопросов в будущем (я думаю, что доступ к блочным переменным вопросам - это новые вопросы о сохранении/выпуске) – ikuramedia

Смежные вопросы