2009-07-23 1 views

ответ

8

Эти два метода делают разные вещи. Если у вас есть таймер (вы его сохранили или выделили или скопировали), вы должны его отпустить. Если вы запланировали его в цикле выполнения, тогда вы должны аннулировать его для цикла запуска, чтобы его освободить. Если вы сделали обе эти вещи, вы должны освободить и отменить таймер (однако, как правило, достаточно иметь цикл выполнения, владеющий таймером).

+0

первый выпуск, а затем недействительный в освобождении? Могу ли я отправить аргумент с двумя аргументами в селектор? – 2009-07-23 12:12:32

+0

Сначала аннулируйте его, затем отпустите его (если вы его владеете). Пожалуйста, уточните свой последний вопрос. Если вы спрашиваете, можете ли вы назвать недействительным и освободить таймер только с одним вызовом, ответ будет отрицательным, если вы не создадите свой собственный метод удобства, который выполняет эти две функции, и вызовите этот метод. – Felixyz

+0

Могу ли я отправить дополнительный аргумент с @selector в NSTIMER? – 2009-07-23 12:44:25

0

Это правильный способ освободить таймер, который все еще может работать (и вы хотите остановить).

+1

Предполагая, что вы владеете таймером в первую очередь ... если вы этого не сделаете, вызов '-release' выйдет из строя. Или должен. – 2009-07-23 12:44:46

1

Всегда, релиз - последнее, что вы делаете. Как только вы отпустите что-то, нет никакой гарантии, что можно безопасно разыменовать объект, а это значит, что он более небезопасен для отправки ЛЮБЫХ сообщений.

15

[timer release] нужно только вызывать, если вы «владеете» таймером. От Apple's documentation:

Поскольку цикл запуска поддерживает таймер, с точки зрения управления памятью нет, как правило, нет необходимости держать ссылку на таймер, как только вы запланировали его. Поскольку таймер передается в качестве аргумента при указании его метода в качестве селектора, вы можете сделать недействительным повторяющийся таймер, когда это необходимо в этом методе. Однако во многих ситуациях вы также хотите отключить таймер, возможно, даже до его запуска. В этом случае вам нужно сохранить ссылку на таймер, чтобы вы могли отправить ему сообщение о недействительности всякий раз, когда это уместно. Если вы создаете незапланированный таймер (см. “Unscheduled Timers”), тогда вы должны поддерживать сильную ссылку на таймер (в среде с подсчетом ссылок, вы его сохраняете), чтобы он не был освобожден до его использования.

Что это значит?

Если вас alloc и init таймер, вы должны также release это, например, так:

NSTimer * timer = [[NSTimer alloc] initWith...]; 

NSRunLoop * runLoop = [NSRunLoop currentRunLoop]; 
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode]; 
[timer release]; 

... 
... 

[timer invalidate]; 
timer = nil; 

После того, как таймер был добавлен цикл выполнения, нет оснований держать ссылку на него больше , так как им управляют петли запуска. В этом случае, как показано, вы должны установить release таймер, как только вы добавите его в цикл запуска, а затем просто invalidate его, когда вы закончите. Окончательная линия (установочный таймер до nil) предназначена для обеспечения безопасности. Вызов invalidate приведет к тому, что таймер будет освобожден (по циклу запуска), поэтому небезопасно поддерживать ссылку, указывающую на него. Установка локальной ссылки на nil сохраняет вещи кошерными.

Если, однако, вы создать таймер, используя один из удобных методов, как так:

NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...]; 

Вы делаете не нужно позвонить [timer release] на всех! Метод удобства добавляет таймер в цикл выполнения, который затем владеет им, поэтому вам не нужно выполнять управление памятью на возвращаемом объекте таймера.Вы бы просто invalidate таймер, когда вы больше не хотите использовать:

[timer invalidate]; 
timer = nil; 

Или, если таймер не был установлен, чтобы повторить, вы бы сделать абсолютно ничего, так как он будет выпущен после его первого вызова ,

+2

, как только вы назовете [освобождение таймера], это не очень хорошая форма, чтобы предположить, что таймер остается в силе. В случае одного метода вы почти всегда можете это сделать, но код был бы лучше, если бы [таймер релиза] был помещен после [таймер invalidate]. –

+0

Отличный практический ответ. – Ross

Смежные вопросы