NSTimer - настроить простой ваниль - не стреляет - PullRequest
1 голос
/ 22 марта 2011

Компиляция в XCode 3.1.1 для цели OSX 10.5.8, 32-разрядной версии и сборки i386.

У меня есть модальный цикл выполнения, выполняющийся в wloop NSWindow и vloop NSView.Модальный цикл запускается первым.Он запускается, работает и останавливается, как и ожидалось.Вот начало:

[NSApp runModalForWindow: wloop];

Затем, когда пользователь нажимает левую кнопку мыши, я делаю это:

if (ticking == 0) // ticking is set to zero in its definition, so starts that way
{
    ticking = 1; // don't want to do this more than once per loop
    tickCounter = 0;
    cuckCoo = [NSTimer scheduledTimerWithTimeInterval: 1.0f / 10.0f         // 10x per second
                                               target: self                 // method is here in masterView
                                             selector: @selector(onTick:)   // method
                                             userInfo: nil                  // not used
                                              repeats: YES];                // should repeat
}

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

Теперь, согласно документам, результирующий NSTimer, сохраненный глобально как "cuckCoo", должен автоматически добавляться в текущий цикл выполнения,Текущий цикл выполнения определенно является модальным - в это время другие окна заблокированы, и только окно с намеченным действием мыши принимает сообщения.

Метод, который это вызывает, "onTick", очень прост(потому что я не могу его запустить), расположенный в коде vloop NSView, где все это происходит:

- (void) onTick:(NSTimer*)theTimer
{
    tickCounter += 1;
    NSLog(@"Timer started");
}

Затем, когда пришло время остановить модальный цикл (который работаетхорошо, кстати), я делаю это:

[cuckCoo invalidate];
[NSApp stop: nil];
ticking=0;
cuckCoo = NULL;
NSLog(@"tickCounter=%ld",tickCounter);

ticking и tickCounter являются глобальными longs.

Я не получаю сообщение NSLog изнутри onTick, и tickCounter остается равным нулю, так каксообщается NSLog в конце runloop.

Все это компилируется и работает нормально.Я просто никогда не получаю никаких тиков.Я в полной растерянности.Любые идеи, кто-нибудь?

Ответы [ 2 ]

3 голосов
/ 22 марта 2011

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

При вызове - [NSTimer scheduleTimerWithTimeInterval: target: selector: userInfo: repeats:] он сразу же планирует таймер, но только для режима по умолчанию, а не для режима модального запуска.Идея заключается в том, что приложение обычно не должно продолжать работать за модальной панелью.

Чтобы создать таймер, который срабатывает во время модального цикла запуска, вы можете использовать - [NSTimer initWithFireDate: interval: target: selector: userInfo: repeat:], а затем - [NSRunLoop addTimer: forMode:].

1 голос
/ 23 марта 2011

Ответ, специфичный для ...

[NSApp runModalForWindow: wloop];

..., после ввода модального цикла выполнения:

NSRunLoop *crl;

    cuckCoo = [NSTimer timerWithTimeInterval: 1.0 / 10
                                      target: self
                                    selector: @selector(onTick:)
                                    userInfo: nil
                                     repeats:YES];
    crl = [NSRunLoop currentRunLoop];
    [crl addTimer: cuckCoo forMode: NSModalPanelRunLoopMode];

(crl получен отдельно для ясности) Гдеметод onTick имеет вид:

- (void) onTick:(NSTimer*)theTimer
{
    // do something tick-tocky
}
...