2010-10-19 3 views

ответ

-1

у вас есть действительно хороший ответ о NSTimer здесь How do I use NSTimer? там они говорят о останавливая повторяющуюся NSTimer делает

[myTimer invalidate]; 
+14

Это неправильно - и это очень плохой совет! Управление памятью с помощью NSTimer очень своеобразно: он сохраняет цель и не освобождает ее до тех пор, пока она не будет признана недействительной. Если он создает повторяющийся NSTimer с самим собой в качестве цели, поэтому таймер сохраняет себя, и поэтому dealloc не будет вызываться до * после * таймер недействителен. Поэтому не говорите «остановите таймер» в * вашем методе dealloc ». Хитрость заключается в том, чтобы найти место для остановки таймера * до * метода dealloc. – matt

+0

Проголосовали по тем же причинам, что и матовый. Необходимо отключить и отпустить таймер за пределами dealloc. – theLastNightTrain

-3

Вам не нужно, чтобы освободить его, потому что он будет autoreleased. Все, что создается методом удобства (т. Е. Вы не вызываете alloc), является обязанностью вызываемой функции для управления памятью, что обычно означает, что он вызовет autorelease на объект, который он создает, прежде чем он вернет его.

Я бы назначил таймер для свойства с ключевым словом retain, но, чтобы убедиться, что он не освобождается от вас. Обычно автореализованные объекты освобождаются в цикле событий, если у них нет сохраненных объектов.

+1

Это неправильно. Таймер сохраняется на NSRunLoop, по которому он запланирован. Он не освобождается, пока не будет признан недействительным. – matt

1

Действительный NSTimer удерживается цикл выполнения, который, если он повторяется, будет навсегда или пока вы не аннулируете его. Вы не должны отпускать его, так как в вашем примере кода вы явно не сохранили его. Если вы аннулируете его, он больше не будет сохранен в цикле выполнения и будет автореализован.

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

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

self.timer = nil; 
+0

Вы уверены, что установка объекта на 'nil' будет вызывать выпуск на нем в объекте-c? – keith

15

То, как вы делаете это, вы никогда не ударил dealloc. Таймер сохраняет свою цель. В этом случае это означает, что таймер сохранил вас. Он не освободит вас, пока не будет признан недействительным. Поскольку вы создали таймер, вы также должны аннулировать его в какой-то момент до dealloc, поскольку сохранение таймера будет препятствовать тому, чтобы ваш объект был dealloc ed.

У вас есть два варианта:

  • найти другое место, чтобы аннулирует таймер (вид идет закадровым, приложение завершает, что ты)
  • набора что-то еще в качестве цели таймера.

В качестве примера последнего:

@interface GameLoopTimerTarget : NSObject { 
    id owner; /* not retained! */ 
} 
- (id)initWithOwner:(id)owner; 
- (void)timerDidFire:(NSTimer *)t; 
@end 

@implementation GameLoopTimerTarget 
- (id)initWithOwner:(id)owner_ { 
    self = [super init]; 
    if (!self) return nil; 

    owner = owner_; 
    return self; 
} 

- (void)timerDidFire:(NSTimer *)t { 
#pragma unused (t) 
    [owner performSelector:@selector(gameLoop)]; 
} 
@end 

/* In your main object… */ 
/* assume synthesized: 
@property (retain, NS_NONATOMIC_IPHONE_ONLY) GameLoopTimer *mainTimerTarget; */ 
- (void)mainTimerLoop { 
    self.mainTimerTarget = [[[GameLoopTimerTarget alloc] initWithOwner:self] autorelease]; 
    mainTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0 target:self.mainTimerTarget selector:@selector(timerDidFire:) userInfo:nil repeats:YES]; 
} 

- (void)dealloc { 
    /* other stuff */ 
    [timer invalidate], timer = nil; 
    [mainTimerTarget release], mainTimerTarget = nil; 
    /* more stuff */ 
    [super dealloc]; 
} 

Обратите внимание, как интервал времени является 1.0/10.0 - это также может быть написана 0.1, но не может быть написано 1/10, поскольку это подразделение будет укоротить до 0.0.

заметить также, как это нарушает цикл сохранения:

  • И вы, и таймер удержания цели таймера.
  • Вы удаляете dealloc в обычное время.
  • Затем вы аннулируете таймер и отпускаете цель таймера.
  • Точка таймера затем освобождается.
+0

Большое вам спасибо, это было действительно полезно! –

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