The timer inside the global queue does not ring on iOS

-(void)viewDidLoad{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSTimer scheduledTimerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        }
    );
}

-(void)action_Timer{
    LOG("Timer called");
}

action_Timernot called. I do not know why. Do you have any ideas?

+5
source share
2 answers

You are invoking a +[NSTimer scheduledTimerWithTimeInterval:...]GCD from the workflow. GCD worker threads do not start a run loop. That is why your first attempt did not work.

When you tried [[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode], you sent the message to the main run loop from the GCD workflow. The problem there is NSRunLoopnot thread safe. (This is described in the NSRunLoop Class Reference .)

Instead, you need to send it back to the main queue so that when sending a message addTimer:...to the main run loop, this is done in the main thread.

-(void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        });        
    });
}

, , . , :

-(void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"on background queue");
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"on main queue");
            [NSTimer scheduledTimerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        });        
    });
}

, , . , , :

-(void)action_Timer {
    // This is called on the main queue, so dispatch to a background queue.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        LOG("Timer called");
    });
}
+14

, ivar :

-(void)viewDidLoad{
        // on the main queue
        self.mytimer = [NSTimer scheduledTimerWithTimeInterval:0.10 
                                                        target:self 
                                                      selector:@selector(action_Timer) 
                                                      userInfo:nil 
                                                        repeats:YES];
        [[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
}

-(void)action_Timer{
    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        LOG("Timer called");
    });
}

. - , , viewDidUnlod dealloc, [self.myTimer invalidate]; self.myTimer = nil;.

+1

All Articles