2010-06-03 10 views
4

Première question débutant: Quelle est la différence entre un sélecteur et une méthode? Question de débutant (qui aurait pensé): Je dois boucler du code basé sur des variables d'instance et faire une pause entre les boucles jusqu'à ce que certaines conditions (bien sûr basées sur des variables d'instance) soient satisfaites. J'ai regardé dormir, j'ai regardé NSThread. Dans les deux discussions à travers ces options, beaucoup ont demandé pourquoi je n'utilise pas NSTimer, alors je suis là.Accès aux variables d'instance à partir du sélecteur NSTimer

Ok, donc c'est assez simple pour obtenir une méthode (sélecteur?) De tirer sur un calendrier. Le problème que j'ai, c'est que je ne sais pas comment voir les variables d'instance que j'ai configurées en dehors du timer depuis le code NSTimer. J'ai besoin de voir ces variables du code sélecteur de NSTimer comme I 1) mettra à jour leurs valeurs et 2) établira des étiquettes basées sur ces valeurs.

Voici un peu de code qui montre le concept ... finalement, j'aurais invalidé les temporisateurs basés sur myVariable, mais j'ai exclu cela pour la clarté du code.

MyClass *aMyClassInstance = [MyClass new]; 
[aMyClassInstance setMyVariable:0]; 
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doStuff) userInfo:nil repeats:YES]; 
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(doSomeOtherStuff) userInfo:nil repeats:YES]; 

- (void) doStuff { 
     [aMyClassInstance setMyVariable:11]; // don't actually have access to set aMyClassInstance.myVariable 
     [self updateSomeUILabel:[NSNumber numberWithInt:aMyClassInstance.myVariable]]; // don't actually have access to aMyClassInstance.myVariable 
} 

- (void) doSomeOtherStuff { 
     [aMyClassInstance setMyVariable:22]; // don't actually have access to set aMyClassInstance.myVariable 
     [self updateSomeUILabel:[NSNumber numberWithInt:aMyClassInstance.myVariable]]; // don't actually have access to aMyClassInstance.myVariable 
} 

- (void) updateSomeUILabel:(NSNumber *)arg{ 
     int value = [arg intValue]; 
     someUILabel.text = [NSString stringWithFormat:@"myVariable = %d", value]; // Updates the UI with new instance variable values 
} 

Répondre

7

Vous pouvez utiliser le paramètre userInfo pour transmettre objet arbitraire. Dans ce cas, vous passez aMyClassInstance InfoUtil:

MyClass *aMyClassInstance = [MyClass new]; 
[aMyClassInstance setMyVariable:0]; 
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doStuff) userInfo:aMyClassInstance repeats:YES]; 

Dans le rappel de la minuterie (qui MUST prend un paramètre), vous revenez le userInfo de la minuterie et jette:

- (void) doStuff:(NSTimer *)timer { 
    MyClass *instance = (MyClass *)[timer userInfo]; 
    [instance setMyVariable:11]; 
    [self updateSomeUILabel:[NSNumber numberWithInt:instance.myVariable]]; 
} 

NLFA chose est que le temporisateur conserve le paramètre userInfo.

+0

Existe-t-il un moyen d'accéder aux variables d'instance de plusieurs instances? – Timbo

+0

Oui. Il suffit de les placer dans un NSDictionary, de passer le dictionnaire sous userInfo et de les récupérer à volonté. –

+0

Vous êtes trop bon, merci beaucoup pour votre aide :) – Timbo

0

Vous avez accès aux variables d'instance si vous définissez l'instance comme la cible de la minuterie comme ceci:

[NSTimer scheduledTimerWithTimeInterval:1.0 target:aMyClassInstance selector:@selector(doStuff) userInfo:nil repeats:YES]; 

L'instance (que vous avez parlé comme aMyClassInstance) sera self .


Sinon, vous pouvez mettre aMyClassInstance et tout autre objet dans le dictionnaire userInfo. Vous faire comme ceci:

NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys: 
          aMyClassInstance, @"a", 
          bMyClassInstance, @"b", 
          cMyClassInstance, @"c", 
          nil]; 
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doStuff:) userInfo:userInfo repeats:YES]; 

Ensuite, dans le sélecteur doStuff:, vous pouvez les récupérer sur comme ceci:

-(void) doStuff:(NSTimer*)timer; 
{ 
    MyClass* aMyClassInstance = [[timer userInfo] objectForKey:@"a"]; 
    MyClass* bMyClassInstance = [[timer userInfo] objectForKey:@"b"]; 
    MyClass* cMyClassInstance = [[timer userInfo] objectForKey:@"c"]; 

    //do whatever you want here 
} 
+0

Intéressant ...existe-t-il un moyen d'accéder aux variables d'instance de plusieurs objets? Par exemple, si j'avais des variables qui affecteraient le résultat de l'événement chronométré dans aMyClassInstance, bMyClassInstance, cMyClassInstance, someOtherClassInstance, etc etc? – Timbo

+0

Vous avez juste besoin de garder les pointeurs vers eux quelque part. Vous pouvez en faire tous les ivars de la cible, ou vous pouvez les mettre tous dans un 'NSDictionary' que vous passez comme argument' userInfo'. Vous n'aurez pas d'accès direct aux variables d'instance de tous les objets, mais vous aurez accès à l'interface publique des objets qui peuvent être utilisés pour atteindre la même fin. –

+0

Merci pour l'info, j'essaie de travailler à travers les tenants et les aboutissants de NSDictionary maintenant. Êtes-vous capable de donner un exemple de la façon dont j'utiliserais NSDictionary pour stocker un pointeur sur aMyClassInstance dans un NSDictionary, et comment je référencerais ce dictionnaire à partir de la méthode NSTimer? – Timbo

1

Une de vos questions portait sur la différence entre un sélecteur et une méthode.

Un sélecteur “ sélectionne ” la méthode à utiliser à partir d'un objet. Imaginez que vous aviez des classes d'animaux, disons Dog, Cat, et Bird, toutes les sous-classes de Animal. Ils implémentent tous une méthode appelée makeSound. Chaque classe aura sa propre implémentation de makeSound, sinon tous les animaux auront le même son. Donc, tous les animaux ont une méthode différente pour faire un son, mais vous obtenez que chaque animal fasse son bruit en utilisant le même sélecteur. Vous sélectionnez la méthode makeSound d'un animal, en d'autres termes.

+0

Ok ça a du sens, merci! – Timbo

Questions connexes