Изменить интервал NSTimer для повторения таймера - PullRequest
5 голосов
/ 09 июня 2010

Я запускаю mainCoop в Какао, используя NSTimer, настроенный следующим образом:

        mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/fps target:self selector:@selector(mainloop) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode];

При запуске программы я установил timeInterval в 0.0, чтобы основной цикл работал как можно быстрее.В любом случае, я хотел бы предоставить функцию для установки частоты кадров (и, следовательно, временного интервала таймера) на конкретное значение во время выполнения.К сожалению, насколько я знаю, это означает, что я должен повторно инициализировать таймер, поскольку Какао не предоставляет такую ​​функцию, как "setTimerInterval". Это то, что я пробовал:

    - (void)setFrameRate:(float)aFps
{
    NSLog(@"setFrameRate");
    [mainLoopTimer invalidate];
    mainLoopTimer = nil;

    mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/aFps target:self selector:@selector(mainloop) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode];
}

, но это вызывает следующую ошибку и останавливаетmainloop:

2010-06-09 11: 14: 15,88 myTarget [7313: a0f] setFrameRate 2010-06-09 11: 14: 15,88 myTarget [7313: a0f] * __NSAutoreleaseNoPool (): Объект 0x40cd80 класса __NSCFDate автоматически освобожден без пула на месте - только утечка 2010-06-09 11: 14: 15.869 myTarget [7313: a0f] * __NSAutoreleaseNoPool (): Объект 0x40e700 класса NSCFTimer автоматически выпущен без пула вместо - просто утечка 0.614628

Я также пытался воссоздать таймер, используя ключевое слово "retain", но это ничего не изменило.Любые идеи о том, как динамически изменить интервал NSTimer во время выполнения?

Спасибо!

Ответы [ 3 ]

3 голосов
/ 11 ноября 2011

Я знаю, эта тема удивительно старая!Но я тоже искал функциональность!

Поскольку выяснилось, что NSTimes не предоставляет эту функцию, я решил создать собственную.Это не лучшее решение, но в моем случае это было единственно возможным.

Я определил переменную "BOOL keepOn;"в моем заголовке.

-(IBAction)doSomething:(id)sender
{
    // Any action to throw every interval.
}

-(IBAction)switchAutoLoad:(id)sender
{
    if([autoLoad state] == NSOffState)
    {
        NSLog(@"auto-reload on!");

        self performSelector:@selector(fireTimer) withObject:nil afterDelay:0];
        keepOn = YES;
        [autoLoad setState:NSOnState];
    }
    else
    {
        NSLog(@"auto-reload off!");
        keepOn = NO;
        [autoLoad setState:NSOffState];
    }
}

-(void)fireTimer
{
    [self doSomething:nil];

    float theTime = 20; // This is the time interval.

    if(keepOn)
    {
        [self performSelector:@selector(fireTimer) withObject:nil afterDelay:theTime];
    }
}

Проблема (очень) бис заключается в том, что «таймер» ожидает всю задержку, прежде чем он сможет получить новое значение.Видите ли, он не реагирует быстро :)) И вы не можете остановить его немедленно (нужно дождаться окончания задержки).

И если вы остановите его, он выполнит еще одно действие, как предполагалось.1010 *

На самом деле это работает для меня и подходит для небольших приложений и инструментов.

0 голосов
/ 09 июня 2010

Вы можете попробовать отменить регистрацию предыдущего таймера и запустить новый с другой частотой. Вы можете отменить регистрацию по

[yourOldTimer invalidate];
yourOldTimer = nil;

Это может решить цель.

0 голосов
/ 09 июня 2010

Вы не должны выпускать mainLoopTimer.
Когда вы его создали, вы получили автоматически выпущенный экземпляр, и runloop сохраняет ссылку на этот экземпляр.
Он будет освобожден при удалении его из цикла: есливы отпускаете его вручную, он удаляется, и runloop пытается получить доступ к недопустимому объекту.
Вот почему он падает.

РЕДАКТИРОВАТЬ: я полностью неправильно прочитал, и я думал, что видел выпуск, когда он был недействительным, извините,Кажется, проблема в том, что AutoreleasePool на месте нет.Обычно это делается в main (): сначала создайте пул автоматического выпуска

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

и отпустите его перед выходом из main.

Посмотрите здесь для документации по пускам Авто-релизов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...