2010-04-16 14 views
27

Estoy tratando de pasar datos a través de userInfo para una llamada NSTimer. ¿Cuál es la mejor manera de hacer esto? Estoy tratando de usar un NSDictionary, esto es bastante simple cuando tengo objetos Objective-C, pero ¿y otros datos? Yo a querer hacer algo como esto, que no funciona como es:Pasar datos a través de NSTimer UserInfo

- (void)play:(SystemSoundID)sound target:(id)target callbackSelector:(SEL)selector 
{ 
    NSLog(@"pause ipod"); 
    [iPodController pause]; 
    theSound = sound; 

    NSMutableDictionary *cb = [[NSMutableDictionary alloc] init]; 
    [cb setObject:(id)&sound forKey:@"sound"]; 
    [cb setObject:target forKey:@"target"]; 
    [cb setObject:(id)&selector forKey:@"selector"]; 

    [NSTimer scheduledTimerWithTimeInterval:0 
            target:self 
            selector:@selector(notifyPause1:) 
            userInfo:(id)cb 
            repeats:NO]; 
} 
+0

¿Es 'cb' nil cuando se llega a' -notifyPause1: '? –

Respuesta

7

Su llamada es correcto, pero no tiene que emitir el diccionario de Identificación. Usted puede obtener el userInfo atrás con la siguiente línea en sus notifyPause1: Método:

- (void)notifyPause1:(NSTimer *)timer { 

    NSDictionary *dict = [timer userInfo]; 

} 
2

sound y selector no son objetos Objective-C: sound es un número sin signo y selector es un puntero a una estructura C. Es probable que cause un colapso de algún tipo.

Querrá usar NSValue para mantener el valor de selector y NSNumber para mantener el valor de sound. NSValue y NSNumber son objetos y funcionarán con NSMutableDictionary.

0

No debe convertir sus objetos a la identificación al asignarlos al diccionario. Cualquier objeto que se pueda incrustar directamente en NSDictionary ya se deriva de NSObject y se considera implícitamente lanzado a id. tienda el nombre del selector como NSString (usando NSStringFromSelector()) y luego volver a convertirlo en un selector utilizando NSSelectorFromString()

Noel

49

Tienes que envuelva la información correctamente en el diccionario:

- (void) play:(SystemSoundID)sound target:(id)target callbackSelector:(SEL)selector 
{ 
    NSLog(@"pause ipod"); 
    [iPodController pause]; 
    theSound = sound; 

    NSMutableDictionary *cb = [[NSMutableDictionary alloc] init]; 
    [cb setObject:[NSNumber numberWithInt:sound] forKey:@"sound"]; 
    [cb setObject:target forKey:@"target"]; 
    [cb setObject:NSStringFromSelector(selector) forKey:@"selector"]; 

    [NSTimer scheduledTimerWithTimeInterval:0 
            target:self 
            selector:@selector(notifyPause1:) 
            userInfo:cb 
            repeats:NO]; 
    [cb release]; 

} 
En

notifyPause1:, recupera todo:

- (void)notifyPause1:(NSTimer *)timer { 
    NSDictionary *dict = [timer userInfo]; 

    SystemSoundID sound = [[dict objectForKey:@"sound"] intValue]; 
    id target = [dict objectForKey:@"target"]; 
    SEL selector = NSSelectorFromString([dict objectForKey:@"selector"]); 

    // Do whatever... 
} 

Como el temporizador es un temporizador repetitivo, ya no necesita el diccionario, por lo que puede liberarlo.

+0

Un aviso: si llama * invalida * para su NSTimer, asegúrese de marcar * isValid * antes de acceder a * userInfo *. Esto se establece en la propiedad docs for * userInfo *, y acabo de recibir un bloqueo en ese lugar exacto. – NAlexN

6

Usted puede solicitar el temporizador en el método dado al selector,

Entonces se puede agarrar useInfo de ese temporizador (timer.userInfo):

- (void)settingTimer 
{ 
[NSTimer scheduledTimerWithTimeInterval:kYourTimeInterval 
           target:self 
           selector:@selector(timerFired:) 
           userInfo:yourObject 
           repeats:NO]; 
} 

- (void)timerFired:(NSTimer*)theTimer 
{ 
    id yourObject = theTimer.userInfo; 
    //your code here 
} 
método
2

de Laurent Etiemble funciona bien para hacer un buen uso de los métodos de temporizador en subclases de UIViewcontroller que se pueden usar fácilmente en una cantidad de controladores de vista diferentes.

A continuación se muestra una forma de escribir una visualización de puntuación genérica que se puede utilizar una y otra vez en la misma aplicación pasando la vista a través de NSTimer userInfo.

.h (subclase de UIViewController)

- (NSTimeInterval) timeSet; 
    - (void) timeRun: (UISegmentedControl*)scoreDisplay; 
    - (void) timeWrite: (NSTimer *)timer; 

.m

  - (NSTimeInterval) timeSet { 
       return [self.startTime timeIntervalSinceNow]; 
      } 

      - (void) timeWrite: (NSTimer *)timer 
      { 
       NSDictionary *dict = [timer userInfo]; 
       UISegmentedControl *scoreDisplay = [dict objectForKey:@"scoreDisplay"]; 

       int myint = round([self timeSet]); 
       NSString* buttonWrite = [[[NSString stringWithFormat:@"Score: %d", self.answered] stringByAppendingString:[NSString stringWithFormat:@" Errors: %d", self.errors]] stringByAppendingString:[NSString stringWithFormat:@" Time: %d", (myint*-1)]]; 

       [scoreDisplay setTitle:buttonWrite forSegmentAtIndex:0]; 
      } 

      - (void) timeRun: (UISegmentedControl*)scoreDisplay 
      { 
       self.startTime = [NSDate date]; 

       NSMutableDictionary *cb = [[NSMutableDictionary alloc] init]; 
       [cb setObject:scoreDisplay forKey:@"scoreDisplay"]; 

       self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1 
                   target:self 
                   selector:@selector(timeWrite:) 
                   userInfo:cb 
                   repeats:YES]; 

      } 

En el controlador de vista

.m

- (void)viewDidLoad 
    { 
     [super viewDidLoad]; 

     //load ScoreDisplay 
     [self timeRun:self.scoreDisplay]; 

    } 
Cuestiones relacionadas