ios objective-c nstimer nsrunloop

ios - NSTimer me pide que lo agregue a un runloop



objective-c nsrunloop (6)

Agregar el temporizador al runloop no funcionó en mi caso. Tuve que crear el temporizador en el hilo principal. Estaba haciendo esta creación de hilos en un delegado MultipeerConnectivity.

dispatch_async(dispatch_get_main_queue(), ^{ self.timer = [NSTimer scheduledTimerWithTimeInterval:self.interval invocation: self.invocation repeats:YES]; });

Me pregunto si alguien puede explicar por qué enviar de vuelta a la cola principal y crear un NSTimer repetitivo. NSTimer Tengo que agregarlo a RUN LOOP para que también se dispare? Incluso cuando utilizo performselectorOnMainThread , todavía tengo que agregarlo a RUN LOOP para activarlo.

A continuación se muestra un ejemplo de mi pregunta:

#define queue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) #define mainqueue dispatch_get_main_queue() - (void)someMethodBeginCalled { dispatch_async(queue, ^{ int x = 0; dispatch_async(mainqueue, ^(void){ if([_delegate respondsToSelector:@selector(complete:)]) [_delegate complete:nil]; }); }); } - (void)compelete:(id)object { [self startTimer]; //[self performSelectorOnMainThread:@selector(startTimer) withObject:nil waitUntilDone:NO]; } - (void)startTimer { NSTimer timer = [NSTimer timerWithTimeInterval:3 target:self selector:@selector(callsomethingelse) userInfo:nil repeats:YES]; //NSDefaultRunLoopMode [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes]; }

EDIT: Creo que redacté esta pregunta muy mal. Me gustaría saber por qué [[NSRunLoop currentRunLoop] addTimer:_busTimer forMode:NSRunLoopCommonModes]; es necesario en startTimer si llamo a someMethodBeginCalled . Si no incluyo esa línea, el temporizador no se dispara.

Si llamo a startTimer desde viewDidLoad por ejemplo, puedo eliminar la línea NSRunLoop y el temporizador se activará cada 60 segundos.



No se llamará al método de temporizador ya que las colas GCD crean subprocesos que no tienen bucles de ejecución

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { NSLog(@"Timer method from GCD main queue"); }]; });

Sin embargo, cuando se envía en la cola principal, se llamará al método del temporizador, ya que se agregará al bucle de ejecución de los hilos principales.

dispatch_async(dispatch_get_main_queue(), ^{ [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) { NSLog(@"Timer method from GCD main queue"); }]; });


Porque, como dicen los docs :

Los temporizadores funcionan en conjunto con los bucles de ejecución. Para utilizar un temporizador de manera efectiva, debe saber cómo funcionan los bucles de ejecución; consulte la Guía de programación de subprocesos y NSRunLoop. Tenga en cuenta, en particular, que los bucles de ejecución conservan sus temporizadores, por lo que puede liberar un temporizador después de haberlo agregado a un bucle de ejecución.

Es una decisión de diseño que Apple tomó cuando escribió el código para NSTimer (y estoy seguro de que tenían buenas razones para hacerlo) y no hay nada que podamos hacer para evitarlo. ¿Es realmente tan pesado?


Siempre puedes usar este método en su lugar:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(getBusLocation) userInfo:nil repeats:YES];

Esto le ahorrará una línea, ya que la agregará al bucle de ejecución automáticamente.


Y aquí es cómo agregar un NSTimer a un runloop:

NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; [runLoop addTimer:timer forMode:NSDefaultRunLoopMode];