Управление памятью NSTimer - нужно ли его присваивать переменной? - PullRequest
1 голос
/ 02 октября 2011

Всякий раз, когда я хочу сделать таймер, я просто делаю:

[NSTimer scheduledTimerWithTimeInterval:5.0 
                                 target:self 
                               selector:@selector(someMethod) 
                               userInfo:nil 
                                repeats:NO];

вместо

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

Первая утечка памяти? Как правильно их использовать?

Ответы [ 3 ]

7 голосов
/ 02 октября 2011

У вас нет проблем с памятью в любом фрагменте; вам просто нужно сделать выбор в отношении ваших потребностей во взаимодействии с таймером.

Когда вы планируете таймер, цикл выполнения сохраняет его, и ссылка на таймер передается, когда он срабатывает, и его селектор - например, (void) doTimerThing: (NSTimer *)tim 1 -, поэтому Вам не нужно строго помещать его в переменную и сохранять его самостоятельно. Apple довольно ясно объясняет это в разделе «Управление памятью» документа «Темы программирования таймера».

Если, однако, вы захотите сделать недействительным таймер до того, как сработает (или между срабатываниями для повторяющегося таймера), вам нужно иметь ссылку на него. В этом случае, это также хорошая идея, чтобы вызвать retain на нем. Метод scheduledTimerWithTimeInterval:target:... возвращает объект, которым вы не владеете, и вам не следует делать предположения о состоянии памяти объектов, которыми вы не владеете (в том числе, находятся ли они в пуле автоматического выпуска или нет, или как долго выполняется цикл выполнения). собираюсь держать таймер рядом). Если вам нужен таймер (или любой другой объект), вы должны заявить о владении им, позвонив по номеру retain.


1 Обратите внимание, что метод таймера всегда должен иметь один параметр ; Селектор в вашем фрагменте выглядит так, как будто это метод, которого нет. Таймер, кажется, работает таким образом, но вы работаете вопреки документированному интерфейсу.

4 голосов
/ 02 октября 2011

В дополнение к предыдущим ответам, если вам не нужен повторяющийся таймер, вы можете использовать

[self performSelector:@selector(someMethod) withObject:nil afterDelay:5.0];

вместо создания таймера вручную.

3 голосов
/ 02 октября 2011

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

Как следует из соглашения о присвоении имен, учитывая имя scheduledTimerWithTimeInterval:... метода, вы знаете, что он вернет автоматически выпущенный объект (или, если быть более точным, он вернет объект, владельцем которого вы не являетесь, и для которого вам не нужно будет отправлять релиз самостоятельно)

Вам не нужно хранить ссылку на созданный NSTimer, если не нужно: таймер будет запланирован на RunLoop (и это RunLoop, который будет сохранять его до тех пор, пока он не будет использован, и освободить его, когда закончите, так что вам не нужно беспокоиться), так что он будет жить сам по себе.

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

...