ваша проблема в том, как вы ее выпустите:
- (void)viewDidLoad{
[super viewDidLoad];
self.tstImageView = [[UIImageView alloc] //<==This object is leaking
initWithFrame:<SomeFrame>];
self.tstImageView.image = [UIImage imageNamed:@"SomeImage.png"];
[self.view addSubview:tstImageView];
[tstImageView release]; // << here
}
Вы должны сделать это следующим образом:
- (void)viewDidLoad{
[super viewDidLoad];
UIImageView * imageView = [[UIImageView alloc] initWithFrame:<SomeFrame>];
imageView.image = [UIImage imageNamed:@"SomeImage.png"];
self.tstImageView = imageView;
[imageView release];
[self.view addSubview:self.tstImageView];
}
Проверка правильна, потому что она не может предполагать, что переменная идентична той, которую вы установили. Поэтому форма, которую вы используете в OP, может привести к дисбалансу количества ссылок, поскольку значение ивара может не совпадать с тем, которое вы ему присвоили к моменту публикации сообщения на иваре.
Эти случаи маловероятны для UIImageView
и весьма маловероятны в контексте вашей программы, но эти примеры должны дать вам представление о том, почему средство проверки предполагает, что ассоциации объект-> ивар не следует доверять:
Между созданием представления изображения и сообщением о его выпуске через ivar у вас есть:
self.tstImageView = [[UIImageView alloc] initWithFrame:<SomeFrame>];
self.tstImageView.image = [UIImage imageNamed:@"SomeImage.png"];
[self.view addSubview:tstImageView];
1) присвоение вида изображения через сеттер
2) доступ к просмотру изображения через геттер
3) прямой доступ к ivar, при добавлении в self.view
- Сеттер мог скопировать или использовать кэшированное значение.
UIImageView
является плохим примером, но контролер не знает, как обычно передаются типы - даже если бы он это сделал, он (иногда) делал небезопасные предположения.
самый простой пример:
- (void)setName:(NSString *)inName {
NSString * prev = name;
if (inName == prev) return;
if (0 == [inName count]) name = @"";
else name = [inName copy];
[prev release];
}
- значение, удерживаемое иваром, может тем временем измениться. вряд ли проблема в этом случае, но допустим, что добавление представления изображения в качестве подпредставления может в конечном итоге перезвонить и изменить
self
в процессе / эффекте добавления подпредставления, а также заменить или удалить представление изображения, которое вы передали. В этом случае передаваемое вами представление переменной будет иметь утечку, а представление, которым оно заменено, будет иметь отрицательный дисбаланс.
Ни один из них не может произойти в вашем примере, но это происходит в реальных программах, и средство проверки корректно оценивается на основе местоположения, а не свойства (средство проверки не может предполагать большую часть что происходит внутри вызова метода). Это также поощряет один хороший идиоматический стиль в этом случае.
РЕДАКТИРОВАТЬ: есть ли утечка там?
Хорошо, я запускаю вышеупомянутый проект, используя
Инструмент утечки в инструменте. Утечки не было, хотя я пытался
это много раз .. Кому я должен верить? Статический анализатор или утечка
инструмент?
Статический анализатор сообщает, что существует потенциальная утечка , потому что он не может гарантировать, что задание / распределение, которое он следует, правильно сохраняется / освобождается. Вы можете гарантировать правильность подсчета ссылок и порадовать статический анализатор, изменив свою программу так, как я написал в своем примере.
То, как вы написали это, сделало невозможным для анализатора следовать указаниям.
Если у вас нет утечек и зомби, значит, утечки нет. Но решение легко исправить - и программы могут меняться в процессе разработки. Пользоваться формой, которую я разместил, намного проще, так что для инструментария и для вас легче проверить правильность программы. Статический анализатор не всегда корректен, но вы должны настроить свои программы так, чтобы он понравился, потому что статический анализ очень полезен. Размещенную мною программу также легче понять и подтвердить, что она правильная.