2012-06-24 4 views
2

У меня есть подкласса UIView, который не освобождается. Я знаю, что только один класс создает экземпляр моего представления. На мой взгляд, у меня есть NSTimer ivar. Если я прокомментирую этот таймер и когда я нажимаю кнопку отмены, которая находится на этом контроллере представления, вызывается dealloc в этом представлении. Если я не закомментирую таймер, dealloc никогда не вызывается.Подкласс UIView не освобождается

//CustomUIView 
- (id) initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain]; 
    } 
} 

Я хочу сохранить ссылку на этот таймер, потому что есть моменты, когда я хочу приостановить таймер. Теперь у меня может быть свойство на моем представлении для таймера и в методе dealloc класса, который имеет ссылку на мой пользовательский uiview, я мог бы аннулировать его перед выпуском указанного представления. Мне не нравится этот подход, потому что я не хочу показывать этот таймер внешним объектам.

У кого-нибудь есть идеи?

+2

NSTimer сохраняет свою цель ... – fbernardo

ответ

6

NSTimer always retains its target. Это имеет два последствия:

  1. Вы не должны иметь вид (который является мишенью таймера) сохранить таймер, так как это создаст цикл.

  2. Ваш взгляд никогда не будет освобожден, пока таймер останется активным.

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

Обычно это происходит, когда вид удаляется из его супервизора; если вы хотите, чтобы он продолжал использовать свой таймер до тех пор, пока это не произойдет, а затем отпустите, вы можете переопределить removeFromSuperview, чтобы аннулировать таймер, а затем позвонить super.

+0

Как этот ответ может иметь только один взлет? (Ну, теперь два ...) Переопределение removeFromSuperview было для меня ключом, спасибо Рикстеру. –

0

Edit:

В вашем методе -dealloc, попробуйте следующее:

- (void) dealloc 
{ 
    [_pollTimer invalidate]; 

    /* 
     If not using ARC: 
     [_pollTimer release], _pollTimer = nil; 
     [super dealloc]; 
    */ 
} 

Вы забыли назвать реализацию super «s из -initWithFrame:! Упс!

- (id) initWithFrame:(CGRect)frame 
{ 
    if ((self = [super initWithFrame:frame])) 
    { 
     _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain]; 
    } 

    return self; 
} 

Это должно работать намного лучше.

+0

Фактически, я делаю это. извините забыл, но это в моем фрагменте кода. – developerdoug

+2

Если NSTimer сохраняет свою цель, счетчик удержания не достигнет нуля, и, следовательно, объект не будет 'dealloc'ed. Вам нужно извлечь этот код из dealloc и вызвать его в другом месте, когда вы закончите с этим представлением. – Rob

1

Вы не должны сохранять таймер. Запланируйте такой таймер: _pollTimer = [NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES]; и всякий раз, когда вы хотите его аннулировать: [_pollTimer invalidate]

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