Souci avec performSelector

Bonjour,



J'essaie de changer le type d'un bouton



Pas de souci avec le code suivant
<br />
NSButton *button;<br />
<br />
[button setButtonType:NSRadioButton];<br />
<br />




Par contre, un test avec performSelector


<br />
<br />
NSNumber *vt = [NSNumber numberWithUnsignedInteger:NSRadioButton];<br />
<br />
[button performSelector:@selector(setButtonType:) withObject:vt];<br />
<br />




Cela ne marche pas !



Une piste ??



Merci

Réponses

  • Parce que NSRadioButton est un integer, mais avec le performSelector:withObject: tu lui passes un objet (NSNumber*) et non un integer.
  • Faut que tu surcharges -setButtonType pour décortiquer ton NSNumber en int.
  • à  la place de ton performSelector qui n'accepte que les objets en paramètre, tu peux utiliser une NSInvocation.
  • CéroceCéroce Membre, Modérateur
    Pour ma culture personnelle, pourquoi utiliser performSelector:? Dans quels cas est-il plus avantageux que d'appeler la méthode directement ? Je me pose juste naà¯vement la question, n'ayant jamais utilisé que makeObjectsPerformSelector:.
  • J'avoue que je ne l'utilise pas souvent non plus.

    Mais combiné à  NSSelectorFromString ça peut être utile dans certains cas.
  • Dans son cas je ne pense pas que ça serve à  grand chose. C'est quand même pratique quand tu veux appeler une méthode que le compilateur ne peut pas connaà®tre lors de ton build.
  • AliGatorAliGator Membre, Modérateur
    Si tu ne connais pas la méthode lors de ton build, tu ne connais pas non plus le type de ses arguments, si ?



    Si c'est pour choisir parmi plusieurs selector qui ont le même nom ou des choses comme ça, y'a pas de mystère : performSelector:withObject: ne marche qu'avec des paramètres de type "id", donc des objets. Pour les autres types et signatures, tu dois utiliser NSInvocation.



    Si tu as à  l'utiliser à  plusieurs reprises dans ton code, ça vaut le coup de faire une méthode générique qui construit la NSInvocation et prend un nombre variable d'arguments avec lesquels il remplit la NSInvocation avant de l'appeler... la méthode en question à  mettre au point prendra quelques lignes, mais après à  utiliser ça sera un vrai bonheur...
  • Les seuls fois où j'utilise un perfermSelector, c'est avec du afterDelay...
  • Avec du afterDelay ? Mias pourquoi faire?

    A moins que tu ais besoin d'être compatible iOS3, sinon tu peux utiliser dispatch_after à  la place (ouais je suis assez fan de GCD ^^)
  • AliGatorAliGator Membre, Modérateur
    juillet 2012 modifié #11
    dispatch_after powaaaa !



    Et sinon pour l'équivalent d'un performSelector tout court (sans afterDelay) mais à  qui on veut passer des arguments de type autre qu'un objet, au lieu d'utiliser des NSInvocation, on peut aussi récupérer la fonction C associée au @selector de l'objet, et appeler la fonction C ensuite ! Il faut juste penser à  caster le pointeur de fonction retourné correctement. (Voir la doc ici entre autres) :
    SEL selector = @selector(setButtonType:); // Le selector à  appeler<br />
    // typer correctement le pointeur de fonction retourné, qui prend (en plus des 2 premiers arguments cachés id et SEL) un NSButtonType en argument<br />
    void (*setButtonTypeFct)(id, SEL, NSButtonType) = (void (*)(id, SEL, NSButtonType))[target methodForSelector:selector];<br />
    <br />
    <br />
    // Appeler ainsi (au lieu du performSelector:withObject:)<br />
    setButtonTypeFct(button, selector, NSRadioButton);
    
  • Merci Ali et aux autres intervenants,



    Je vais voir si cela donne de bons résultats
Connectez-vous ou Inscrivez-vous pour répondre.