Утечка указывает на то, что ваша переменная создается в этой точке, так что утечка находится не там, где она начинается.Вам необходимо освободить transientData в вашем методе отмены, подобном этому
- (void)cancelDownload
{
[self.connectionDatas cancel];
self.transientData = nil;
}
Существует несколько проблем с несогласованностью в вашем стиле кодирования, которые могут затруднить вам умственное отслеживание происходящего.Если вы придерживаетесь своих собственных стандартов, вам будет легче следить за ходом процесса.
Это потенциально может привести к другой утечке
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (!self.transientData) {
self.transientData = [[NSMutableData alloc] init]; // leaky line
}
[self.transientData setLength:0];
}
Вызов [[NSMutableData alloc] init]
создает экземпляр NSMutableData
со счетом удержания +1.Затем, если вы используете свойства (которые лучше всего) с retain
, тогда self.transientData =
возьмет еще одно сохранение, добавив еще один +1 к счету удержания.Позднее он выпускается только один раз, поэтому у вас есть утечка, поскольку NSMutableData
все еще будет зависать.
Далее в своем коде вы используете шаблон
- create instance и назначайтелокальной переменной
- назначить экземпляр ivar
- выпустить экземпляр локальной переменной
Это шаблон, который я использовал бы, когда меня нет в методе init
.Поэтому предыдущий метод должен быть изменен на:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (!self.transientData) {
NSMutableData *tmpTransientData = [[NSMutableData alloc] init];
self.transientData = tmpTransientData;
[tmpTransientData release];
}
[self.transientData setLength:0];
}
Преимущество в том, что вы не используете авто-релиз, поэтому вы более четко определяете, когда объект больше не требуется, что предпочтительнее, когда это возможно на устройствах с небольшой памятью..
Еще одно несоответствие, которое может принести пользу, приведя в порядок немного, - это то, как вы выпускаете свои ивары.Вы сделали это взаимозаменяемо в своем коде
[self.transientData release];
self.transientData = nil;
Я бы использовал последнее в моем коде (не в dealloc
) для переменных экземпляра, так как установщик synthesized
вызовет для вас release
и установите указатель на nil
, что значительно безопаснее.