2010-06-09 26 views
5

estoy corriendo un Mainloop en Cocoa usando un NSTimer configurado de esta manera:intervalo de cambio NSTimer para repetir temporizador

 mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/fps target:self selector:@selector(mainloop) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode]; 

al inicio del programa que establezca el timeInterval a 0,0 para que el mainloop corre tan rápido como sea posible. De todos modos, me gustaría proporcionar una función para establecer la velocidad de fotogramas (y por lo tanto el intervalo de tiempo del temporizador) a un valor específico en el tiempo de ejecución. Por desgracia, por lo que yo se que significa que tengo que reiniciar el temporizador desde el cacao no proporciona una función como "setTimerInterval" Esto es lo que he intentado:

- (void)setFrameRate:(float)aFps 
{ 
    NSLog(@"setFrameRate"); 
    [mainLoopTimer invalidate]; 
    mainLoopTimer = nil; 

    mainLoopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/aFps target:self selector:@selector(mainloop) userInfo:nil repeats:YES]; 
    [[NSRunLoop currentRunLoop] addTimer:mainLoopTimer forMode:NSEventTrackingRunLoopMode]; 
} 

pero esto arroja el siguiente error y detiene el mainloop :

2010-06-09 11: 14: 15.868 MyTarget [7313: a0f] setFrameRate 2010-06-09 11: 14: 15.868 MyTarget [7313: a0f] * __NSAutoreleaseNoPool(): Object 0x40cd80 de clase __NSCFDate autorellenada sin ningún grupo en su lugar - solo goteando 2010-06-09 11: 14: 15.869 myTarget [7313: a0f] * __NSAutoreleaseNoPool(): Object 0x40e700 de clase NSCFTimer autoreleased sin piscina en su lugar - sólo fugas 0,614628

También traté de recrear el temporizador usando la palabra clave "mantener", pero eso no cambia nada. ¿Alguna idea sobre cómo cambiar dinámicamente el intervalo de un NSTimer en tiempo de ejecución?

Gracias!

Respuesta

0

No debe soltar mainLoopTimer.
Cuando lo creó, recibió una instancia autorrellenada y el runloop conserva la referencia a esa instancia.
Se liberará cuando lo elimine del bucle: si lo suelta manualmente, se elimina y el bucle de ejecución intenta acceder a un objeto no válido.
Es por eso que falla.

EDIT: Lo leí mal por completo y pensé que vi la liberación cuando fue una invalidación, lo siento. El problema parece ser que no hay AutoreleasePool en su lugar. Esto se hace generalmente en main(): crear la agrupación autorelease como la primera cosa

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

y liberarlo justo antes de salir de la principal.

Eche un vistazo a here para ver la documentación de las piscinas autorizadas.

+0

¿Qué debo hacer para cambiar el intervalo? – moka

+0

Perdón. Leí mal [lanzamiento de MainLoopTimer]. Está actuando correctamente con el temporizador, pero parece que AutoReleasePool no está en su lugar. échale un vistazo aquí: http://developer.apple.com/mac/library/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html – garph0

+0

hmm Ya intenté poner un autoreleasepool en su lugar, pero no funcionó , pero lo intentaré de nuevo! – moka

-2

Puede intentar anular el registro del temporizador anterior y comenzar uno nuevo con una frecuencia diferente. puede anular el registro por

[yourOldTimer invalidate]; 
yourOldTimer = nil; 

Esto podría resolver el propósito.

+0

como pueden ver, eso es lo que ya hice, y no funciona. – moka

3

Lo sé, este hilo es increíble viejo! ¡Pero también estaba buscando la funcionalidad!

Como resultó que NSTimes no proporciona esta característica, decidí crear una propia. No es la mejor solución, pero en mi caso fue la única posible.

Definí la variable "BOOL keepOn;" en mi encabezado

-(IBAction)doSomething:(id)sender 
{ 
    // Any action to throw every interval. 
} 

-(IBAction)switchAutoLoad:(id)sender 
{ 
    if([autoLoad state] == NSOffState) 
    { 
     NSLog(@"auto-reload on!"); 

     self performSelector:@selector(fireTimer) withObject:nil afterDelay:0]; 
     keepOn = YES; 
     [autoLoad setState:NSOnState]; 
    } 
    else 
    { 
     NSLog(@"auto-reload off!"); 
     keepOn = NO; 
     [autoLoad setState:NSOffState]; 
    } 
} 

-(void)fireTimer 
{ 
    [self doSomething:nil]; 

    float theTime = 20; // This is the time interval. 

    if(keepOn) 
    { 
     [self performSelector:@selector(fireTimer) withObject:nil afterDelay:theTime]; 
    } 
} 

La (muy) bis cuestión es, que el "temporizador" está esperando toda la demora, antes de que pueda obtener un nuevo valor. Como ve, no responde rápido :)) Y no puede detenerlo inmediatamente (tiene que esperar a que termine el retraso).

Y si lo detiene, está lanzando una acción más como se suponía.

Actualmente funciona para mi y está bien para pequeñas aplicaciones y herramientas.

Cuestiones relacionadas