Точечная запись, отпускание и освобождение

@интерфейс:

UIImageView *myImageView;

@property (nonatomic, retain) UIImageView *myImageView;

@выполнение:

@synthesize myImageView;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
}

Каков счетчик ссылок для myImageView? 2 (1 из alloc, 1 из точечной нотации сохранить) или 3 (1 из alloc, 1 из точечной нотации сохранить, 1 из @property сохранить)

У этих двух операторов одинаковое количество ссылок?

self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];

и

myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];

Кроме того, я предполагаю, что вы выпускаете их в @implemenation и в методе dealloc, верно?


РЕДАКТИРОВАТЬ:

Я не получил того ответа, который хотел, возможно, мой вопрос расплывчатый. Я понимаю, что такое точечная нотация, @property, @synthesize и как работают сеттеры и геттеры. Чего я не понимаю, так это того, что происходит при использовании «я». и без «себя». относительно удержания счетчика. Я действительно запустил метод keepCount для объекта myImageView, и он подтвердил мой оригинал, «я». case сразу же имеет счетчик сохранения два (с выделением и сохранением свойств, поэтому, вероятно, будет хорошей идеей использовать там autorelease). Теперь это приводит к другому вопросу: если бы я не использовал автоспуск, как мне это сделать? Release один раз в viewDidLoad и еще раз в dealloc все равно приведет к утечке памяти, верно?

self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
NSLog(@"retain count dot: %d", [myImageView retainCount]);

2011-05-17 10: 01: 14.915 Тест [1249: 207] сохраняет количество точек: 2

myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
NSLog(@"retain count: %d", [myImageView retainCount]);

2011-05-17 10: 03: 14.715 Тест [1278: 207] сохраняет счет: 1


person s2000coder    schedule 16.05.2011    source источник
comment
Не думайте о сохраненных счетчиках как об абсолютных значениях; думайте о них как о дельтах. Т.е. alloc дает объект со счетчиком ссылок +1, self.myImageView = aView добавляет единицу к счетчику ссылок, release уменьшает счетчик удержания на единицу .....   -  person bbum    schedule 16.05.2011
comment
@bbum, понял, но я пытаюсь понять различия при прямом использовании оценщика собственности и ivar. Должен ли я по-прежнему выпустить оба в viewDidLoad (поскольку я размещаю там) и снова освободить его в dealloc, потому что это свойство сохранения.   -  person s2000coder    schedule 16.05.2011
comment
Подсчитайте удержания, которые вы вызываете, и сбалансируйте каждое с выпуском; +alloc - это одно, присвоение свойству через сеттер - другое ... так что да, вам нужно два релиза или авто-релиза. Это так просто; если вы сохраните, вы должны отпустить.   -  person bbum    schedule 16.05.2011
comment
так что для второго случая использования оценщика @property я должен выпустить его дважды: один в viewDidLoad для + alloc и release в dealloc для сохранения? А как насчет первого случая?   -  person s2000coder    schedule 16.05.2011


Ответы (3)


Во-первых: вам не следует делать никаких предположений относительно количества ссылок. В лучшем случае это будет вводить в заблуждение.

Если вы используете доступ к свойству (self.myImageView = ...), он будет сохранен автоматически, таким образом, вы утекаете UIImageView в viewDidLoad. Вы должны использовать что-то вроде

self.myImageView = [[[UIMageView alloc] init.... ] autorelease];

Ваш последний пример (без доступа «точка») изменит ivar напрямую, поэтому утечка этого нового экземпляра не произойдет. НО это приведет к утечке старого imageView, которое вы переопределите, если не отпустите его раньше.

Я настоятельно рекомендую использовать доступ к собственности все время. И не забудьте очистить в dealloc:

[myImageView release], myImageView = nil;

Некоторые люди предпочитают self.myImageView = nil;, но это может иметь побочные эффекты.

person Eiko    schedule 16.05.2011
comment
В первом случае, использующем доступ к свойствам, мне пришлось бы освободить его в viewDidLoad и в dealloc, верно? (поскольку счетчик ссылок равен 2). А во втором случае мне не нужно выпускать его в viewDidLoad и просто в методе dealloc? Вот где я запутался. - person s2000coder; 16.05.2011
comment
В основном да. Но точечный синтаксис также корректно освобождает старые объекты - это действительно рекомендуется. Кроме того, вы можете использовать self.myImageView = nil; в viewDidUnload, но это другое дело. Руководство по программированию управления памятью очень хорошо читается. - person Eiko; 17.05.2011

нет, они не такие. Первый «сохраняет», тем самым увеличивая счетчик ссылок. Итак, либо вы сначала назначаете его временной переменной, а затем отпускаете (в первом случае) [альтернативно, добавляете 'autorelease' и уходите без временной переменной], либо вы проверяете, что imageView уже не назначен (и если есть - отпустите) во втором случае.

person Roman    schedule 16.05.2011
comment
self.myImageView = alloc ... и [выпуск myImageView] в viewDidLoad совпадает с myImageView = alloc ... и [выпуск myImageView]? .... и отпустить еще раз в методе dealloc? - person s2000coder; 16.05.2011
comment
Извините, если мой комментарий выше был непонятен. Я имел в виду, что в обоих случаях вам все равно нужно выпустить дважды, верно? - person s2000coder; 16.05.2011

Чтобы добавить к первому ответу, установщик точечной нотации заботится об управлении памятью, связанной с освобождением старого объекта и сохранением нового. Во втором случае у вас будет огромная потенциальная утечка памяти, поскольку каждый раз, когда это вызывается, удержание увеличивается на 1. Не в случае с установщиком точечной нотации.

Однако, поскольку он сохраняет объект, вам необходимо освободить исходное выделение.

person Jamie    schedule 16.05.2011