Почему этот релиз не работает? - PullRequest
0 голосов
/ 22 мая 2010

У меня есть вопрос новичка о следующем:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSArray *anArray;
    anArray = [dictionary objectForKey: [NSString stringWithFormat:@"%d", section]];
    //here dictionary is of type NSDictionary, initialized in another place.
    AnObject *obj = [[AnObject alloc] init];
    obj = [anArray objectAtIndex:0];
    [anArray release];
    return obj.title;
}

Если я запустлю его как есть, я получу ошибку. Если я не поставлю [релиз anArray], он будет работать нормально. Я не совсем понимаю, почему это происходит?

Спасибо.

Ответы [ 3 ]

2 голосов
/ 22 мая 2010

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

Вы вступаете во владение объектом, если создаете его с помощью метода, имя которого начинается с «alloc» или «new» или содержит «copy» (например, alloc, newObject или mutableCopy), или если вы отправляете ему сохранить сообщение. Вы несете ответственность за отказ от владения принадлежащими вам объектами с помощью выпуска или автоматического выпуска. В любой другой раз, когда вы получаете объект, вы должны не отпустить его.

Теперь посмотрим, как вы получили массив. Вы использовали метод objectForKey: он не начинается с alloc, new и не содержит copy. Вы также не сохранили массив. Следовательно, вы не являетесь владельцем массива anArray. Вы не должны выпускать это.

Приведенное выше правило является самой важной вещью, которую нужно знать при программировании с помощью Cocoa на iPhone или Mac без сбора мусора. На одном из других постеров в качестве вспомогательного воспоминания была предложена аббревиатура NARC (New Alloc Retain Copy).

Давайте применим правило к переменной obj в вашем коде. Вы получили это с помощью вызова alloc, поэтому вы несете ответственность за его освобождение. Однако затем вы получили его снова (перезаписав предыдущее значение) с помощью вызова objectForIndex: поэтому после этого вы не должны его освобождать. Тем не менее, первое значение действительно нужно было выпустить и теперь утекло. на самом деле, строка alloc не нужна.

1 голос
/ 22 мая 2010

anArray не выделен, не сохранен, не скопирован или не создан вами, поэтому вам не нужно его выпускать.

Кроме того, у вас есть утечка, когда вы создаете совершенно новый AnObject экземпляр использует alloc / init, но затем присваивает ему новое значение сразу из массива.

Ваш код должен выглядеть следующим образом:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSArray *anArray;
    anArray = [dictionary objectForKey: [NSString stringWithFormat:@"%d", section]];
    //here dictionary is of type NSDictionary, initialized in another place.
    AnObject *obj = [anArray objectAtIndex:0];
    return obj.title;
}
1 голос
/ 22 мая 2010

Вам не нужно выпускать массив, потому что вы его не создаете. Словарь просто дает вам указатель на тот, который у него есть.

Похоже, у вас есть утечка памяти при создании объекта AnObject. На следующей строке вы переназначаете переменную "obj", чтобы она была чем-то, что вы получаете из anArray Но вы не выпустили созданный вами AnObject в строке выше.

Я думаю, ваш код должен выглядеть так:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSArray *anArray;
    anArray = [dictionary objectForKey: [NSString stringWithFormat:@"%d", section]];
    //here dictionary is of type NSDictionary, initialized in another place.
    obj = [anArray objectAtIndex:0];
    return obj.title;
}

Вам не нужно освобождать то, что вы не создали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...