Estoy usando un NSTimer a hacer algo de renderizado OpenGL basado en la aplicación de iPhone. Tengo un cuadro de diálogo modal que se abre y las solicitudes de entrada de usuario. Mientras que el usuario está proporcionando entrada me gustaría «pausa», es decir, algo como esto:

[myNSTimer pause];

Estoy usando esta sintaxis porque he estado haciendo cosas como:

[myNSTimer invalidate];

cuando quiero que se detenga.

¿Cómo puedo programación pausa el NSTimer?

  • el enlace está roto
InformationsquelleAutor MrDatabase | 2008-12-07

15 Comentarios

  1. 22

    Desde aquí:

    http://discussions.apple.com/thread.jspa?threadID=1811475&tstart=75

    «Usted puede almacenar la cantidad de tiempo que ha pasado desde que el temporizador de empezar… Cuando el tiempo comienza a almacenar la fecha en un NSDate variable. A continuación, cuando el usuario cambia de… usar el método timeIntervalSinceNow en el NSDate clase para almacenar cuánto tiempo ha pasado… tenga en cuenta que esto le dará un valor negativo para timeIntervalSinceNow. Cuando el usuario regresa utilizar ese valor para establecer un adecuado temporizador.

    No creo que hay una manera para hacer una pausa y reiniciar el temporizador. Me enfrenté a una situación similar. «

    • Gracias por la respuesta. Tal vez puede ser resuelto por deshacerse de el primer contador de tiempo… luego de hacer una completamente nueva temporizador después de que el usuario proporciona la entrada.
    • Para pausar el temporizador, envía ‘anular’ mensaje a su temporizador y la puso a cero después. Para reanudar el temporizador, a continuación, en [NSTimer el armado de…..]. Básicamente, deshacerse de lo viejo y, a continuación, crear una nueva con las mismas propiedades. Lo que me pareció la manera más fácil 🙂
    • Que no es el mismo aunque. Si se hace una pausa el temporizador va a tener algo de tiempo antes de que el próximo evento de temporizador. Si, en lugar de descartarlo y empezar uno nuevo, siempre tendrá el original de la cantidad de tiempo antes de un evento, lo cual es incorrecto.
  2. 35

    Sólo el pensamiento de la actualización de pequeñas correcciones a la kapesoftware‘s respuesta:

    NSDate *pauseStart, *previousFireDate;
    
    -(void) pauseTimer:(NSTimer *)timer { 
    
        pauseStart = [[NSDate dateWithTimeIntervalSinceNow:0] retain];
    
        previousFireDate = [[timer fireDate] retain];
    
        [timer setFireDate:[NSDate distantFuture]];
    }
    
    -(void) resumeTimer:(NSTimer *)timer {
    
        float pauseTime = -1*[pauseStart timeIntervalSinceNow];
    
        [timer setFireDate:[previousFireDate initWithTimeInterval:pauseTime sinceDate:previousFireDate]];
    
        [pauseStart release];
    
        [previousFireDate release];
    }
    • esto funciona bien pero cuando voy a hacer una pausa ..su pausar el tiempo y cuando lo cuento…se inicia con la hora actual
    • En lugar de [NSDate dateWithTimeIntervalSinceNow:0] usted puede simplemente hacer [NSDate date].
  3. 12

    La forma en que he logrado este fue mediante el almacenamiento de la NSTimer el despido de fecha en una variable y, a continuación, configuración de la cocción de la fecha hasta el INFINITO.

    Cuando hago una pausa:

    pauseStart = [[NSDate dateWithTimeIntervalSinceNow:0] retain];
    previousFiringDate = [timer firingDate];
    [timer setFiringDate:INFINITY]

    Cuando puedo volver a agregar la cantidad de tiempo que el reloj se detuvo a las anteriores cocción fecha:

    float pauseTime = -1*[pauseStart timeIntervalSinceNow];
    [timer setFireDate:[previousFireDate initWithTimeInterval:pauseTime sinceDate:previousFireDate]];

    Este hecho que sea mucho más fácil de lo que preocuparse acerca de invalidar y reiniciar el temporizador. Yo tenía un montón de temporizadores lo acabo de poner a todos en un array y lo hizo a todos ellos. Yo subclases de la NSTimer en el fin de mantener la previousFiringDate asociados con temporizador.

    Esto también fue mejor que el uso de un tipo BOOL de si estaba o no en pausa para acciones no tendrá lugar si el BOOL se establece. Esto es debido a que si algo iba a suceder antes de la pausa, no va a suceder después de volver porque se ha omitido.

    • Que pueden funcionar, pero de acuerdo a la referencia doc: Subclassing Notes You should not attempt to subclass NSTimer.
  4. 8

    En mi caso, tuve una variable ‘segundos’ y otro ‘timerIsEnabled’. Cuando yo quería para pausar el temporizador, que acaba de hacer el timerIsEnabled como falsa. Desde los segundos variable fue sólo aumenta si timerIsEnabled era cierto, he solucionado mi problema. Espero que esto ayude.

  5. 8

    La forma más sencilla que he conseguido fue de esta manera:

    -(void) timerToggle{
        if (theTimer == nil) {
            float theInterval = 1.0/30.0;
            theTimer = [NSTimer scheduledTimerWithTimeInterval:theInterval target:self selector:@selector(animateBall:) userInfo:nil repeats:YES];
        } else {
            [theTimer invalidate];
            theTimer = nil;
        }
    }
    • ¿Qué hace el 1.0/30.0 significar?
    • Esa es la tasa de fuego / intervalo en el que el temporizador del selector se llama. En este caso, 1/30 es cada 0,03 s.
  6. 5

    Aquí es una categoría en la NSTimer que permite pausar y reanudar la funcionalidad.

    Encabezado:

    #import <Foundation/Foundation.h>
    
    @interface NSTimer (CVPausable)
    
    - (void)pauseOrResume;
    - (BOOL)isPaused;
    
    @end

    Aplicación:

    #import "NSTimer+CVPausable.h"
    #import <objc/runtime.h>
    
    @interface NSTimer (CVPausablePrivate)
    
    @property (nonatomic) NSNumber *timeDeltaNumber;
    
    @end
    
    @implementation NSTimer (CVPausablePrivate)
    
    static void *AssociationKey;
    
    - (NSNumber *)timeDeltaNumber
    {
        return objc_getAssociatedObject(self, AssociationKey);
    }
    
    - (void)setTimeDeltaNumber:(NSNumber *)timeDeltaNumber
    {
        objc_setAssociatedObject(self, AssociationKey, timeDeltaNumber, OBJC_ASSOCIATION_RETAIN);
    }
    
    @end
    
    
    @implementation NSTimer (CVPausable)
    
    - (void)pauseOrResume
    {
        if ([self isPaused]) {
            self.fireDate = [[NSDate date] dateByAddingTimeInterval:[self.timeDeltaNumber doubleValue]];
            self.timeDeltaNumber = nil;
        }
        else {
            NSTimeInterval interval = [[self fireDate] timeIntervalSinceNow];
            self.timeDeltaNumber = @(interval);
            self.fireDate = [NSDate distantFuture];
        }
    }
    
    - (BOOL)isPaused
    {
        return (self.timeDeltaNumber != nil);
    }
    
    @end
    • Me encanta la categoría de respuestas! Dónde está el libro para que!
  7. 2

    Vieja pregunta, pero yo acabo de escribir un ligero clase de utilidad para lograr exactamente lo OP que está buscando.

    https://github.com/codeslaw/CSPausibleTimer

    Admite la repetición de los temporizadores así. La esperanza viene en práctico!

    • Esto se ve impresionante. Yo voy a echarle un vistazo ahora. Gracias!
    • El código dice que «los derechos de Autor de 2013» y «Todos los derechos reservados.» ¿te importaría si yo lo uso en un posiblemente-proyecto rentable?
    • conejo — sí, por favor. Voy a estar seguro de cambiar el texto de la licencia, cuando tengo la oportunidad. Eres libre de usar el que quieras
    • Genial!!! Gracias por la confirmación.
  8. 2

    Basa en @Thiru y @kapesoftware respuestas, me hizo una Objective-C categoría en NSTimer el uso de Objetos Asociados para poner en pausa y reanudar el temporizador.

    #import <objc/runtime.h>
    
    @interface NSTimer (PausableTimer)
    
    @property (nonatomic, retain) NSDate *pausedDate;
    
    @property (nonatomic, retain) NSDate *nextFireDate;
    
    -(void)pause;
    
    -(void)resume;
    
    @end

    @implementation NSTimer (PausableTimer)
    
    static char * kPausedDate = "pausedDate";
    static char * kNextFireDate = "nextFireDate";
    
    @dynamic pausedDate;
    @dynamic nextFireDate;
    
    -(void)pause {
    
      self.pausedDate = [NSDate date];
    
      self.nextFireDate = [self fireDate];
    
      [self setFireDate:[NSDate distantFuture]];
    }
    
    -(void)resume
    {
      float pauseTime = -1*[self.pausedDate timeIntervalSinceNow];
    
      [self setFireDate:[self.nextFireDate initWithTimeInterval:pauseTime sinceDate:self.nextFireDate]];
    }
    
    - (void)setPausedDate:(NSDate *)pausedDate
    {
      objc_setAssociatedObject(self, kPausedDate, pausedDate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (NSDate *)pausedDate
    {
      return objc_getAssociatedObject(self, kPausedDate);
    }
    
    - (void)setNextFireDate:(NSDate *)nextFireDate
    {
      objc_setAssociatedObject(self, kNextFireDate, nextFireDate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (NSDate *)nextFireDate
    {
      return objc_getAssociatedObject(self, kNextFireDate);
    }

    Mantiene todo en orden y significa que usted no tiene que crear una instancia de variables o propiedades sólo para hacer una pausa y reanudar su temporizadores.

  9. 0

    Usted no puede pausa NSTimer como se mencionó anteriormente. De modo que el tiempo para ser capturado no debe depender de que el Temporizador de firedate ,me sugieren. Aquí está mi solución más sencilla :

    A la hora de crear el temporizador de inicializar la partida unidad de tiempo como:

    self.startDate=[NSDate date];
    self.timeElapsedInterval=[[NSDate date] timeIntervalSinceDate:self.startDate];//This ``will be 0 //second at the start of the timer.``     
    
    myTimer= [NSTimer scheduledTimerWithTimeInterval:1.0 target:self `selector:@selector(updateTimer) userInfo:nil repeats:YES];

    `
    Ahora en la actualización del método de temporizador:

      NSTimeInterval unitTime=1;
    -(void) updateTimer
     {
     if(self.timerPaused)
           {
               //Do nothing as timer is paused
           }
     else{
         self.timerElapsedInterval=timerElapsedInterval+unitInterval;
        //Then do your thing update the visual timer texfield or something.
        }
    
     }
  10. 0

    Bien, esto me parece como el mejor método para implementar la pausa de un temporizador cosa. El uso de una variable estática para alternar pausar y reanudar. En pausa, anular el temporizador y la puso a cero y en la sección de currículum vitae restablecer el temporizador utilizando el código original por el que se inicia.

    El siguiente código funciona en la respuesta a un botón de pausa, haga clic en.

    -(IBAction)Pause:(id)sender
    {
        static BOOL *PauseToggle;
        if(!PauseToggle)
        {
            [timer invalidate];
            timer = nil;
            PauseToggle = (BOOL *) YES;
        }
        else
        {
            timer = [NSTimer scheduledTimerWithTimeInterval:0.04 target:self selector:@selector(HeliMove) userInfo:nil repeats:YES];
            PauseToggle = (BOOL *) NO;
        }
    }
    • Esto no funcionará si el intervalo de tiempo suficientemente largo como para ser perceptible. Si su intervalo de 10 segundos y te pausar el temporizador después de 5 segundos, el temporizador debe tener 5 segundos cuando se activa de nuevo. La solución sería iniciar el temporizador de 10 segundos cuando esté de vuelta en.
    • Estoy usando el temporizador para hacer repita la tarea de no contar el tiempo. Así que, en mi caso estaría resuelto.
  11. 0

    El código de abajo es para el uso con un scrollview, que aporta contenido a intervalos regulares, y los bucles de regreso a la parte delantera de su realización, pero la misma lógica puede ser utilizado por cualquier botón pausa/reanudar.

    El temporizador de incendios en la carga (initiateFeatureTimer), y hace una pausa para la interacción del usuario (comenzará método de arrastrar), lo que permite que el usuario mire contenido por el tiempo como a ella le gusta. Cuando el usuario levanta el dedo (terminará arrastrando) el featurePaused booleano se restablece, pero también, usted tiene la opción de agregar un poco más de retraso.

    De esta manera, la barra de desplazamiento no se mueve de descuento al instante en el dedo ascensor, es más reactivo para el usuario.

    //set vars, fire first method on load.
    featureDelay = 8; //int
    featureInt = featureDelay-1; //int
    featurePaused = false; //boolean
    
    -(void)initiateFeatureTimer {
        featureTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(moveFeatureScroller) userInfo:nil repeats:true];
        [featureTimer fire];
    }
     -(void)moveFeatureScroller {
    
        if (!featurePaused){ //check boolean
            featureInt++;
    
             if (featureInt == featureDelay){
                 featureInt = 0; //reset the feature int
    
                /*//scroll logic
                int nextPage = (featurePage + 1) * w;
                if (featurePage == features.count-1){ nextPage = 0; }
                [featureScroller setContentOffset:CGPointMake(nextPage, 0)]; */          
             }
          }
    }
    
    -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
        featurePaused = true; //pause the timer
    }
    -(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
        featurePaused = false; //restart the timer
        featureInt = -3; //if you want to add an additional delay
    }
  12. 0

    Si el fuego intervalo de tiempo es tolerante, puede utilizar CADisplayLink en lugar de NSTimer. Porque CADisplayLink apoyo -pause.

    displayLink = [[CADisplayLink displayLinkWithTarget:self selector:@selector(fireMethod:)];
    displayLink.frameInterval = approximateVaue;//CADisplayLink's frame rate is 60 fps.
        [displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    //pause
    [displayLink pause];
  13. -1

    Yo también estaba en la necesidad de pausable NSTimer. Después de leer este hilo y sus respuestas y darse cuenta de que lo único que necesito es para configurar el temporizador de la fireDate a un futuro lejano y, a continuación, volver a la Ahora hice categoría a NSTimer con la Pausa y Reanudar métodos. Así que, simplemente, puedo pausar el temporizador de llamadas [myTimer pause]; y reanudar llamando [myTimer reanudar]; métodos. Aquí está, espero que pueda ayudar a alguien.

    Interfaz:

    #import <Foundation/Foundation.h>
    
    @interface NSTimer (Pausable)
    
    -(void)pause;
    -(void)resume;
    
    @end

    Aplicación:

    #import "NSTimer+Pausable.h"
    
    @implementation NSTimer (Pausable)
    
    -(void)pause
    {
        [self setFireDate:[NSDate dateWithTimeIntervalSinceNow:[NSDate distantFuture]]]; //set fireDate to far future
    }
    
    -(void)resume
    {
        [self setFireDate:[NSDate date]];
    }
    
    @end
    • Usted debe utilizar [NSDate distantFuture] en lugar de 31536000
    • Sí, buen punto, gracias
    • dateWithTimeIntervalSinceNow: toma un NSTimeInterval, en lugar de enviarlo [[NSDate distantFuture] timeoutInterval]
    • Después de usar su categoría, parece [self setFireDate:[NSDate distantFuture]] funciona bien. Sin embargo, el curriculum vitae necesita un poco de trabajo para establecer el firedate de vuelta a la hora original.
    • Terminé usando @Carl Veazey del enfoque, con un par de cambios
    • esto es inútil, ya que el método de reanudación acaba de incendios en el momento de la llamada

Dejar respuesta

Please enter your comment!
Please enter your name here