Почему после выделения представления и добавления его в другое представление значение счета становится равным 3? - PullRequest
1 голос
/ 28 августа 2011

Внутри функции didSelectRowAtIndexPath моего UITableViewController я помещаю UIActivityIndicatorView поверх выбранного UITableViewCell, потому что касание этой ячейки потенциально может вызвать медленный запрос к серверу. Я распечатал счет удержания UIActivityIndicatorView и заметил, что это было 3, когда я ожидал, что будет 2.

// @property (nonatomic, retain) UIActivityIndicatorView *spinner;
foo.spinner = [[UIActivityIndicatorView alloc] 
    initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge
];

UITableViewCell *cell = [self.tableView cellForRowAtIndex:indexPath];
[cell addSubView:foo.spinner];

NSLog("retain count of spinner = %d", [foo.spinner retainCount]);

Первое сохранение должно произойти с foo->setSpinner. Второе сохранение должно произойти из tableView, добавляющего счетчик как дочернее представление. Где 3-й удерживают? Как бы вы избежали этой утечки памяти?

Ответы [ 4 ]

7 голосов
/ 28 августа 2011

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

2 голосов
/ 28 августа 2011

Вы должны сделать:

UIActivityIndicatorView *aSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
foo.spinner = aSpinner;
[aSpinner release];

или

foo.spinner = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];

Все остальное в порядке:)

Объяснение:

Помните, что синтезируясвойство типа:

@property (nonatomic, retain) UIActivityIndicatorView *spinner;

в основном похоже на:

- (void)setSpinner:(UIActivityIndicatorView *)aSpinner{
    [aSpinner retain];
    [spinner release];
    spinner = aSpinner;
}

Таким образом, после выполнения foo.spinner = [[UIActivityIndicatorView alloc] init...]; счетчик сохранения будет равен 2 (alloc / init: 1 и 2, поскольку свойство сохраняется),Кроме того, выполнение [someView addSubview:foo.spinner]; увеличит количество сохраняемых единиц на 1, поэтому у вас есть 3:)

1 голос
/ 28 августа 2011

Не звоните retainCount

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

Думайте об удерживаемом счете как о дельте; Вы увеличиваете это, вы уменьшаете это.

Итак, глядя на этот код:

// @property (nonatomic, retain) UIActivityIndicatorView *spinner;

// next line is +1 for the property, +1 for the alloc
foo.spinner = [[UIActivityIndicatorView alloc] 
    initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge
];

UITableViewCell *cell = [self.tableView cellForRowAtIndex:indexPath];

// this line may or may not be +1;  doesn't matter. the cell is taking responsibility for
// foo.spinner and whether it retains it or copies it or ignores it is irrelevant
// (obviously, it most likely retains it, but you shouldn't care)
[cell addSubView:foo.spinner];

Итак, в конце этого у вас есть два приращения счетчика, за которые вы несете ответственность. Хотя вы могли бы дважды вызывать release в dealloc, это было бы против паттерна. Итак, лучше всего сбалансировать +1 от alloc с выпуском:

[foo.spinner release];
1 голос
/ 28 августа 2011

Сохранение счета «поток»:
1. Первое сохранение на alloc
2. Второе foo->setSpinner
3. Третье addSubview

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