На самом деле не ваше дело знать, почему счет сохранения не равен нулю. Сохраняемые значения - это детали реализации, и лучше не обращать на них внимания, если вы можете этого избежать.
Вот что говорит документация invalidate
:
Объект NSRunLoop
удаляет свою сильную ссылку на таймер либо непосредственно перед возвратом метода invalidate, либо в какой-то более поздний момент.
Таким образом, даже не гарантируется, что количество сохраняемых данных будет уменьшено, когда invalidate
вернется.
Кроме того, невозможно когда-либо увидеть, чтобы количество сохраняемых объектов было равно нулю. Когда счет удержания станет равным нулю, объект уничтожается вместо этого, и вы не можете воздействовать (например, на вызов CFGetRetainCount
) на уничтоженный объект. Память объекта, вероятно, была перезаписана, поэтому попытка что-либо сделать с ним - неопределенное поведение.
Тем не менее, мы можем сделать некоторые предположения о том, почему счет удержания по-прежнему равен 2 после invalidate
.
Во-первых, мы знаем, что ваша локальная переменная timer
имеет сильную ссылку на таймер, поэтому на счетчик сохраняется +1.
Селектор scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
не начинается с new
или alloc
или copy
, поэтому он, вероятно, автоматически освобождает объект. Это, вероятно, другой +1 в счет удержания; объект, вероятно, находится в пуле автоматического выпуска. Подробнее см. Руководство по программированию для расширенного управления памятью .
Вы можете проверить теорию автоматического выпуска следующим образом:
NSTimer *timer;
@autoreleasepool {
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
NSLog(@"Timer Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)timer));
[timer invalidate];
NSLog(@"Timer Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)timer));
}
NSLog(@"Timer Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)timer));
// If the retain count is now 1, the timer was in the autoreleasepool,
// and the local `timer` variable now has the only strong reference to
// the timer.