2010-04-16 10 views
27

Próbuję przekazać dane przez userInfo dla wywołania NSTimer. Jaki jest najlepszy sposób na zrobienie tego? Próbuję użyć NSDictionary, jest to dość proste, gdy mam obiekty Objective-C, ale co z innymi danymi? Chcę zrobić coś takiego, co nie działa tak, jak jest:Przekazywanie danych przez 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

Czy 'cb' nil, gdy dojdziesz do' -notifyPause1: '? –

Odpowiedz

7

Twoje połączenie jest prawidłowe, ale nie musisz przesyłać słownika do identyfikatora. Można uzyskać userinfo powraca z kolejnym wierszu w swoim notifyPause1: Metoda:

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

    NSDictionary *dict = [timer userInfo]; 

} 
2

sound i selector nie są objective-c obiekty: sound jest liczbą bez znaku i selector jest wskaźnikiem do C struct. To prawdopodobnie spowoduje pewien rodzaj awarii.

Będziesz chciał użyć wartości NSV do przechowywania wartości dla selector i NSNumber, aby zachować wartość dla sound. NSValue i NSNumber są obiektami i będą działać z NSMutableDictionary.

0

Nie powinieneś rzutować swoich obiektów na id podczas przypisywania do słownika. Każdy obiekt, który można bezpośrednio osadzić w kodzie NSDictionary, już wywodzi się z NSObject i jest domyślnie uznawany za rzutowany na identyfikator. Store nazwa selektora jako NSString (używając NSStringFromSelector()), a następnie przekształcić go z powrotem do selektora przy użyciu NSSelectorFromString()

Claus

49

Trzeba owinąć informacje poprawnie do słownika:

- (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]; 

} 

W notifyPause1: odzyskujesz wszystko:

Ponieważ licznik czasu jest zegarem powtarzalnym, słownik nie jest już potrzebny, więc można go zwolnić.

+0

A heads up - jeśli zadzwonisz * unieważnij * dla swojego NSTimer, upewnij się, że zaznaczyłeś * isValid * przed dostępem do * userInfo *. Jest to powiedziane w dokumentach dotyczących właściwości * userInfo *, a właśnie złapałem awarię w tym miejscu. – NAlexN

6

może poprosić o zegarze w metodzie podanej do selektora,

Następnie można chwycić useInfo z tego timera (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 
} 
metoda
2

Laurent René Etiemble za dobrze do dobrego wykorzystania metod timera w podklasach UIViewcontroller, które mogą być z łatwością wykorzystane w wielu różnych kontrolerach widoku.

Poniżej opisano sposób generowania ogólnego wyniku punktowego, którego można używać wielokrotnie w tej samej aplikacji, przekazując widok za pośrednictwem NSTimer userInfo.

.h (podklasa 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]; 

      } 

W regulatorze widok

.m

- (void)viewDidLoad 
    { 
     [super viewDidLoad]; 

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

    }