iOS5 ARC безопасно ли планировать NSTimers из фоновых селекторов? - PullRequest
4 голосов
/ 09 ноября 2011

Я пытаюсь отладить свое приложение.

Я использовал несколько экземпляров NSTimer в своем коде без дуг, как это (из основного потока):

[NSTimer scheduledTimerWithTimeInterval:5 target:musicPlayer selector:@selector(playPause:) userInfo:nil repeats:NO];

Это работает нормально, если я назначил этот код кнопке и нажал кнопку. Таймер срабатывает.

Я также пробовал:

 if( self.deliveryTimer == nil)
  {                 
self.deliveryTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(playPause:) userInfo:nil repeats:NO];
    }

    -(void)playPause:(NSTimer*)timer
    {
           [deliveryTimer invalidate];
            deliveryTimer = nil;
//more code here

    }

Я ожидал, что таймер запустится, нажмите метод воспроизведения / паузы, приведенный ниже, а затем поверните в ноль, чтобы я мог сбросить таймер позже. Причина, по которой я проверяю nil, состоит в том, что у меня есть 3 разных пути кода, которые могут устанавливать таймер. У каждого есть оператор NSLog, указывающий, что таймер был запланирован.

Мой код выполняется, и я вижу, что таймеры планируются, но, похоже, они не срабатывают в ходе нормального выполнения приложения. Я расследую почему. Кратковременные таймеры, использующие ту же логику, работают нормально Когда я запускаю приложение на некоторое время, у меня возникают проблемы.

Может ли NSTimers быть исправлена ​​ARC?

Имеет ли значение, если я установлю таймер из executeSelectorInBackground? Когда я писал этот вопрос, я заметил, что некоторые из моих таймеров были созданы из пути кода, который вызывается через:

[self performSelectorInBackground:@selector(notifyDelegateOfDataPoint:) withObject:data];

Может ли фоновый селектор быть причиной того, что мои таймеры не срабатывают / не возвращаются раньше?

Любая помощь приветствуется, эта ошибка беспокоит меня уже более 2 недель!

Обновление: после изменения кода для использования основного потока для NSTimers, таймеры работают корректно , вызывая воспроизведение музыки:

   [self performSelectorOnMainThread:@selector(deliverReminder:) withObject:nil waitUntilDone:NO];


-(void)deliverReminder:(id)sender{
     [ NSTimer scheduledTimerWithTimeInterval:10 target:reminderDeliverySystem selector:@selector(playAfterDelay:) userInfo:nil repeats:NO];
    [self postMessageWithTitle:nil message:@"Deliver Reminder Called" action:kNoContextAction];
}

-(void)playAfterDelay:(id)sender
{
    int reminderDelay = reminder.delayValue.intValue;

    [playTimers addObject:[NSTimer scheduledTimerWithTimeInterval:reminderDelay target:self selector:@selector(appMusicPlayerPlay:) userInfo:nil repeats:NO]];


}

Здесь у меня есть целая куча таймеров, потому что я не знаю, как передать примитив цели с помощью селектора.

1 Ответ

6 голосов
/ 09 ноября 2011

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

Если вы хотите использовать свои таймеры в фоновом потоке, вы можете сделать что-то вроде следующего:

NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
self.deliveryTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(playPause:) userInfo:nil repeats:NO];
[runLoop run];

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

Я не верю, что это связано с ARC, хотя там может быть что-то, за чем вам нужно следить, потому что NSRunLoop удерживает таймер, который к нему привязан. Следуя стандартной процедуре с NSTimers, следует избегать проблем с ARC.

...