Is iOS5 ARC safe to schedule NSTimers from background selectors?

I am trying to debug my application.

I used some instances of NSTimer in my non-arduous code like this (from the main thread):

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

This works fine if I assign this code to a button and press the button. The timer is triggering.

I also tried:

  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 } 

I would expect the timer to execute, click the play / pause method below, then turn it to zero so that I can reset the timer later. The reason I check for nil is because I have 3 different code paths that can set a timer. Each of them has an NSLog statement indicating that a timer is scheduled.

My code runs, and I see that the timers are scheduled, but they do not seem to work during normal application execution. Iโ€™m investigating why. Short-term timers using the same logic fire. This is when I let the application work for a while, when I have problems.

Can NSTimers be fixed by ARC?

Does it matter if I set the timer from the performSelectorInBackground function? When I wrote this question, I noticed that some of my timers were created from code that is called through:

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

Could a background selector be the reason why my timers do not fire / not return earlier?

Any help is appreciated, this bug has been listening to me for more than two weeks!

Update: after changing the code to use the main thread for NSTimers, the timers work correctly , causing the music to play:

  [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]]; } 

Here I have a whole group of timers, because I donโ€™t know how to pass goals to the primitive using the selector.

+4
source share
1 answer

NSTimer requires that the loop loop start in this background thread so that it continues to fire. The main thread already has an active loop cycle, so your timers work great when executed on it.

If you want to use your timers in the background thread, you can do something like the following:

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

What probably happened to your timers of shorter duration, but longer ones, is that they fired while the thread was still active, but without a start loop to save it, it failed after the thread reached the end of its execution.

I donโ€™t think this is due to ARC, although there might be something there that you have to keep track of because NSRunLoop is holding onto a timer that is bound to it. Following the standard procedure with NSTimers, problems with ARC should be avoided.

+6
source

Source: https://habr.com/ru/post/1380330/


All Articles