web-dev-qa-db-fra.com

Passing Data par NSTimer UserInfo

J'essaie de transmettre des données via userInfo pour un appel NSTimer. Quelle est la meilleure façon de procéder? J'essaie d'utiliser un NSDictionary, c'est assez simple quand j'ai des objets Objective-C, mais qu'en est-il des autres données? Je veux faire quelque chose comme ça, qui ne fonctionne pas tel quel:

- (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];
}
27
zorro2b

Vous devez intégrer correctement les informations dans le dictionnaire:

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

}

Dans notifyPause1:, vous récupérez tout:

- (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...
}

Comme le minuteur est un minuteur qui se répète, vous n’avez plus besoin du dictionnaire, vous pouvez donc le relâcher.

49
Laurent Etiemble

Votre appel est bon, mais vous n’avez pas à lancer le dictionnaire pour id. Vous pouvez récupérer les informations utilisateur avec la ligne suivante dans votre méthode notifyPause1:

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

    NSDictionary *dict = [timer userInfo];

}
7
schaechtele

Vous pouvez demander la minuterie dans la méthode donnée au sélecteur,

Ensuite, vous pouvez extraire useInfo de ce minuteur ( 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
}
6
avishic

La méthode de Laurent Etiemble fonctionne bien pour faire bon usage des méthodes de minuterie dans les sous-classes de UIViewcontroller qui peuvent être facilement utilisées dans plusieurs contrôleurs de vue.

Vous trouverez ci-dessous un moyen d'écrire un affichage de score générique qui peut être utilisé à plusieurs reprises dans la même application en passant la vue à travers NSTimer userInfo.

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

            }

Dans le contrôleur de vue

.m

  - (void)viewDidLoad
  {
       [super viewDidLoad];

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

  }
2
MGM

sound et selector ne sont pas des objets Objective-C: sound est un nombre non signé et selector est un pointeur sur une structure C. Cela risquerait de provoquer un crash.

Vous voudrez utiliser NSValue pour conserver la valeur de selector et NSNumber pour conserver la valeur de sound. NSValue et NSNumber sont des objets et fonctionneront avec NSMutableDictionary.

2
Giao

Vous ne devez pas convertir vos objets en identifiant lors de l'attribution au dictionnaire. Tout objet pouvant être incorporé directement dans une NSDictionary dérive déjà de NSObject et est implicitement concordé en id. Enregistrez le nom du sélecteur sous la forme NSString (à l'aide de NSStringFromSelector()), puis convertissez-le en sélecteur à l'aide de NSSelectorFromString()

Claus

0
Claus Broch