Присвоение значений переменным экземпляра в задаче C - PullRequest
2 голосов
/ 25 марта 2009

Функция, на которую я смотрю:

-(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, затем назначается указатель с именем * dictionary, а затем назначается переменной экземпляра stateZips? Почему бы не выделить его и не присвоить непосредственно переменной экземпляра, а сохранить память для создания и освобождения другого NSDictionary? Всегда используется одна и та же методология, в том числе и в этой функции с NSArray ...

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

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

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

Ответы [ 3 ]

6 голосов
/ 26 марта 2009

Никто, похоже, не учел тот факт, что линия

self.statesZips = dictionary;

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

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

[[NSDictionary alloc] initWithContentsOfFile:plistPath];

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

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

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

4 голосов
/ 26 марта 2009

Свойство statesZips, вероятно, сохранено, вот почему.

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

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

self.statesZips = [NSDictionary dictionaryWithContentsOfFile:plistPath];

потому что dictionaryWithContentsOfFile возвращает автоматически освобожденный объект.

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

Я предлагаю вам прочитать Руководство по программированию управления памятью для какао для получения дополнительной информации.

РЕДАКТИРОВАТЬ: Должно быть, я пропустил последнюю часть вашего вопроса, когда я впервые прочитал его, но Барри уже ответил на эту часть.

2 голосов
/ 26 марта 2009

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

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

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

звонок

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

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

...