Остановить NSRunLoop из таймера - PullRequest
4 голосов
/ 08 июля 2011

Я сделал RunLoop с таймером, который обновляет метку, которая отображает обратный отсчет.Мне нужно, чтобы RunLoop прекратился, как только обратный отсчет достигнет нуля, для случая, когда таймер обычно заканчивается, я мог бы просто использовать runUntilDate, где текущая дата + время обратного отсчета.Проблема в том, что пользователь отменяет обратный отсчет от кнопки до его завершения.Я не знаю, как сказать RunLoop прекратить действие кнопки отмены.Вот код для RunLoop:

    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                            [self methodSignatureForSelector:@selector(updateCountdownLabel:)]];
[invocation setTarget:self];
[invocation setSelector:@selector(updateCountdownLabel:)];
[[NSRunLoop mainRunLoop] addTimer:[NSTimer timerWithTimeInterval:1 invocation:invocation repeats:YES] forMode:NSRunLoopCommonModes];

Метод просто указывает метке уменьшаться на 1 в каждом цикле.

Я мог бы сказать кнопке отмены изменить метку на ноль, изаставить селектор цикла выполнения проверить, равно ли значение нулю, но может ли собственный селектор RunLoop сказать ему, чтобы он остановился?

cancelPerformSelector:target:argument:

cancelPerformSelectorsWithTarget:

Это самые близкие, что я нашел, но они, кажется, не работают изнутрисобственный селектор RunLoops, или, по крайней мере, не так, как я его пробовал.

По сути, мне нужно, чтобы кнопка велела RunLoop остановиться или каким-то образом остановить RunLoop от своего собственного селектора.

Спасибо.

1 Ответ

13 голосов
/ 08 июля 2011

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

Что вам нужно сделать, это сохранить объект NSTimer, который вы создаете, как переменную экземпляра перед планированием таймера в цикле выполнения.

В вашем updateCountdownLabel: методе, как только ваше конечное условие выполнено, просто вызовите -invalidate в вашем экземпляре таймера. Это удалит таймер из цикла выполнения, и поскольку вы никогда не сохраняли его, он будет освобожден.

Я обновил методы, чтобы использовать селектор на основе NSTimer вместо вашего NSInvocation. Это означает, что сигнатура метода обратного вызова определяется так, как вы ожидаете. Это также избавляет от необходимости хранить объект NSTimer в иваре:

- (void)startCountDown
{

    NSTimer* timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(updateCountdownLabel:) userInfo:nil repeats:YES]
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}


- (void)updateCountdownLabel:(NSTImer*)timer
{
    if(thingsAreAllDone)
    {
        [timer invalidate];
    }
}
...