NSTimer, сохранять или не сохранять - PullRequest
4 голосов
/ 18 мая 2011

Это то, что озадачило меня на некоторое время.

У меня есть NSTimer, добавленный в currentRunLoop, и если я не сохраню его, он вылетает.

NSTimer *timer = [[NSTimer timerWithTimeInterval:60.0 target:self selector:@selector(tryUnion:) userInfo:nil repeats:NO] retain];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

Я прочитал, что мне не нужно его сохранять, так как addTimer для NSRunLoop делает это.

позже я аннулирую и освобождаю (если я не сохраняю выше, я не выпускаю ниже - это случай сбоя):

- (void) tryUnion:(NSTimer*)aTimer {
[aTimer invalidate];
[aTimer release];
}

Мои вопросы 1) Как мне написать это, если возможно сделать то, что я сделал, без сохранения / выпуска. 2) проанализировать флаги этой или потенциальной утечки объекта в «таймере». Как здесь написано, есть ли вероятность утечек или просто анализатор недостаточно умен, чтобы знать, что в функции, вызванной таймером, есть сбой?

Ответы [ 3 ]

4 голосов
/ 18 мая 2011

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

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

повторяется
Если ДА, таймер будет повторно перепланировать себя до тех пор, пока не станет недействительным.Если НЕТ, таймер станет недействительным после его запуска.

Таким образом, вы не должны ни сохранять / освобождать этот таймер, ни делать его недействительным.Огонь и забудь.

Кроме того, если вы используете scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:, добавление таймера в цикл запуска также будет сделано для вас.Таким образом, все ваше будет выглядеть так:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(tryUnion:) userInfo:nil repeats:NO];

Ваша функция таймера не должна ничего делать с aTimer, просто делайте то, что должен делать ваш таймер;таймер будет аннулирован и разблокирован без дальнейшего вмешательства.

1 голос
/ 18 мая 2011

Ну, вы правы в том, что NSTimer не должно быть сохранено.Метод класса +(NSTimer *)timerWithInterval должен, как правило, autorelease это ссылка.

Но сообщение invalidate NSTimer удаляет себя из NSRunLoop, и это освобождает его ссылку (единственную, оставшуюся в то время),Ваш второй [aTimer release] звонок является причиной сбоя.

1 голос
/ 18 мая 2011

При вызове invalidate по таймеру освобождается его, поэтому вам не нужно иметь еще один оператор release.Смотри документы здесь

...