Créer une pause dans le programme

Bonjour



Mon objectif est le suivant : en cliquant sur un bouton, je souhaite que cela fasse apparaà®tre 3 autres boutons ("echelle" "ptADigit" "mizeAZero") . Cependant, je voudrais que ces boutons apparaissent les uns à  la suite des autres, à  0,3 secondes d'intervalle.



J'ai essayé avec NSTimer, mais je n'obtiens pas le résultat voulu : mon 2e bouton n'apparaà®t pas et en revanche, mon 3e apparait bien à  0,3 seconde. Qu'ai-je oublié ??



voici mon code


<br />
//----------------------------------------------------------------------------------------------<br />
-(void) maMethode:(NSTimer *)aTimer // n&#39;est pas déclaréee : elle est demandée en scheduledTimerWithTimeInterval<br />
{<br />
[nomBouton setHidden:NO];<br />
NSLog(@&quot; passé ds maMethode&quot;);<br />
<br />
// si je mets cela dans le else de &quot;pause&quot;, je reste dans &quot;maMethode&quot;<br />
[timer invalidate];<br />
[timer release];<br />
timer = nil;<br />
}<br />
<br />
//----------------------------------------------------------------------------------------------<br />
-(void) pause : (NSButton *)bouton<br />
{<br />
nomBouton = bouton;<br />
<br />
  if(timer == nil)<br />
  {<br />
   timer = [[NSTimer scheduledTimerWithTimeInterval:0.3<br />
			   target:self<br />
			 selector:@selector(maMethode:)<br />
			 userInfo:nil<br />
			  repeats:YES] retain];<br />
   NSLog(@&quot; passé ds pause : debut&quot;);<br />
  }else {<br />
   NSLog(@&quot; passé ds pause :  fin&quot;);<br />
  <br />
  <br />
  }<br />
NSLog(@&quot; passé ds pause :  fin - fin&quot;);<br />
}<br />
<br />
//----------------------------------------------------------------------------------------------<br />
-(IBAction) parametre: (id)sender;<br />
{<br />
<br />
[echelle setHidden:NO];<br />
[self pause:ptADigit];<br />
[self pause:mizeAZero];<br />
<br />
}<br />




Merci d'avance

Réponses

  • Salut,



    Dans un premier temps, je pense que ta variable "timer" est globale. Donc pas besoin de faire un retain/release supplémentaire.

    Cela est géré dans ton objet en global avec la méthode suivante si tu n'as pas ARC.


    <br />
    -(void)dealloc<br />
    {<br />
    	 [super dealloc];<br />
    }<br />
    




    Après, tu peux utiliser la méthodescheduledTimerWithTimeInterval sans retain, c'est une méthode static.

    Ensuite, il faut vérifier que ton StoryBoard paramètre bien tous tes boutons.



    Question bête : "maMethode", je suppose que c'est un exemple. Car tu mets en setHidden:NO qu'un seul bouton.



    Karoxys.
  • AliGatorAliGator Membre, Modérateur
    Pourquoi se compliquer la vie ?

    Pourquoi ne pas faire ça avec CoreAnimation ?
    // AU début, masquer button1, button2 et button3 non pas avec la propriété &quot;hidden&quot; mais en mettant &quot;alpha&quot; à  0<br />
    // Comme ça on peut animer la propriété progressivement, avec un effet de fondu enchaà®né, c&#39;est plus joli<br />
    button1.alpha = 0.0;<br />
    button2.alpha = 0.0;<br />
    button3.alpha = 0.0;<br />
    <br />
    // Puis pour les faire apparaà®tre progressivement :<br />
    [UIView animateWithDuration:0.3 animations:^{<br />
      button1.alpha = 1.0; // faire apparaitre button1 progressivement (alpha qui va augmenter de 0.0 à  1.0)<br />
    } completion:^{<br />
      // une fois l&#39;animation du premier bouton terminée, animer le 2nd bouton<br />
      [UIView animateWithDuration:0.3 animations:^{<br />
        button2.alpha = 1.0; // faire apparaitre button2 par fondu enchaà®né également<br />
      } completion:^{<br />
        // une fois button2 affiché, faire la dernière animation, pour button3<br />
        [UIView animateWithDuration:0.3 animations:^{<br />
          button3.alpha = 1.0;<br />
        }];<br />
      }];<br />
    }];
    
    Et voilà , tout concentré en un seul endroit, pas besoin de timer, et en prime tu as une animation avec un fondu enchaà®né (apparition progressive)



    Pour plus d'infos, lire la doc de UIView, le View Programming Guide, la doc sur les blocks...
  • mpergandmpergand Membre
    juillet 2012 modifié #4
    Ma soluce image/smile.png' class='bbc_emoticon' alt=':)' />



    Créer une méthode pause:
    <br />
    -(void) pause:(NSTimeInterval) time <br />
    {<br />
    NSTimeInterval time1=[NSDate timeIntervalSinceReferenceDate];<br />
    NSTimeInterval time2;<br />
    <br />
    do {<br />
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];<br />
      time2=[NSDate timeIntervalSinceReferenceDate];<br />
      }while((time2-time1)&lt;time);<br />
    }<br />
    <br />
    [color=#666600][color=#666600]-([/color][/color][color=#660066][color=#660066]IBAction[/color][/color][color=#666600][color=#666600])[/color][/color][color=#000000][color=#000000] parametre[/color][/color][color=#666600][color=#666600]:[/color][/color][color=#000000][color=#000000] [/color][/color][color=#666600][color=#666600]([/color][/color][color=#000000][color=#000000]id[/color][/color][color=#666600][color=#666600])[/color][/color][color=#000000][color=#000000]sender[/color][/color][color=#666600][color=#666600];[/color][/color]<br />
    [color=#666600][color=#666600]{[/color][/color]<br />
    [color=#666600][color=#666600][[/color][/color][color=#000000][color=#000000]echelle setHidden[/color][/color][color=#666600][color=#666600]:[/color][/color][color=#000000][color=#000000]NO[/color][/color][color=#666600][color=#666600]];[/color][/color]<br />
    [color=#666600][color=#666600][self pause:.3];[/color][/color]<br />
    [color=#666600][color=#666600][ptADigit[/color][/color][color=#000000][color=#000000] setHidden[/color][/color][color=#666600][color=#666600]:[/color][/color][color=#000000][color=#000000]NO[/color][/color][color=#666600][color=#666600]];[/color][/color]<br />
    [self pause:.3];<br />
    [color=#666600][color=#666600][mizeAZero[/color][/color][color=#000000][color=#000000] setHidden[/color][/color][color=#666600][color=#666600]:[/color][/color][color=#000000][color=#000000]NO[/color][/color][color=#666600][color=#666600]];[/color][/color]<br />
    <br />
    [color=#666600][color=#666600]}[/color][/color]<br />
    
  • AliGatorAliGator Membre, Modérateur
    Mmmmh je suis pas fan de ta soluce mpergand, même si ça utilise les NSRunLoop proprement, ça me donne toujours l'impression que ça fait une attente active (je sais c'est pas le cas mais ça fait bizarre à  lire ^^)



    Quitte à  ne pas vouloir d'animation mais juste une pause, autant faire ça avec GCD et dispatch_after dans ce cas image/tongue.png' class='bbc_emoticon' alt=':P' />
    -(IBAction)parameter:(id)sender {<br />
    <br />
      [echelle setHidden:NO];<br />
      dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC);<br />
      dispatch_after(popTime, dispatch_get_main_queue(), ^{<br />
        [ptADigit setHidden:NO];<br />
    <br />
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC);<br />
        dispatch_after(popTime, dispatch_get_main_queue(), ^{<br />
          [mizeAZero setHidden:NO];<br />
        })<br />
      });<br />
    }
    
    Mais bon, quitte à  faire apparaà®tre les boutons à  0.3s d'intervale, autant en profiter pour les faire apparaà®tre de façon animée.

    J'ai proposé comme animation simple de jouer sur l'alpha. On pourrait imaginer plein d'autres choses, comme les faire grossir, les faire pousser comme des champignons, et ce de façon très simple grâce aux méthodes de UIView image/smile.png' class='bbc_emoticon' alt=':)' />
  • AliGatorAliGator Membre, Modérateur
    Exemple d'animations "rebond", pour permettre d'afficher/masquer button1, button2 et button3 de manière animée et sympa tout en gardant un code sans timer et utilisant CoreAnimation de façon simple :
    void bounceViewUp(UIView* view, dispatch_block_t completion)<br />
    {<br />
        const NSTimeInterval raiseTime = 0.2f;<br />
        const CGFloat bounceScale = 1.3f;<br />
        const NSTimeInterval bounceTime = 0.1;<br />
    <br />
        view.transform = CGAffineTransformMakeScale(CGFLOAT_MIN, CGFLOAT_MIN); // Mettre le bouton à  0% de sa taille (démarrer tout petit)<br />
        view.hidden = NO;<br />
        [UIView animateWithDuration:raiseTime animations:^{<br />
            view.transform = CGAffineTransformMakeScale(bounceScale, bounceScale); // faire grossir le bouton jusqu&#39;à  120% de sa taille finale<br />
        } completion:^(BOOL finished) {<br />
            [UIView animateWithDuration:bounceTime animations:^{<br />
                view.transform = CGAffineTransformIdentity; // une fois à  120%, le faire retomber à  sa taille finale 100%<br />
            } completion:^(BOOL finished) {<br />
                if (completion) completion();<br />
            }];<br />
        }];<br />
    };<br />
    <br />
    void bounceViewDown(UIView* view, dispatch_block_t completion)<br />
    {<br />
        const NSTimeInterval raiseTime = 0.2f;<br />
        const CGFloat bounceScale = 1.3f;<br />
        const NSTimeInterval bounceTime = 0.1;<br />
    <br />
        [UIView animateWithDuration:bounceTime animations:^{<br />
            view.transform = CGAffineTransformMakeScale(bounceScale, bounceScale); // faire grossir le bouton jusqu&#39;à  120% de sa taille<br />
        } completion:^(BOOL finished) {<br />
            [UIView animateWithDuration:raiseTime animations:^{<br />
                view.transform = CGAffineTransformMakeScale(CGFLOAT_MIN, CGFLOAT_MIN); // le faire diminuer jusqu&#39;à  0% (disparition)<br />
            } completion:^(BOOL finished) {<br />
                view.hidden = YES;<br />
                if (completion) completion();<br />
            }];<br />
        }];<br />
    };<br />
    <br />
    <br />
    // Et l&#39;action pour afficher/masquer les 3 boutons (un UISwitch qui affiche ou masque les 3 boutons selon son état)<br />
    - (IBAction)toggle:(UISwitch *)sender<br />
    {    <br />
        if (sender.on)<br />
        {<br />
            // Afficher (animation rebond) button1, puis button2, puis button3<br />
            bounceViewUp(button1, ^{<br />
                bounceViewUp(button2, ^{<br />
                    bounceViewUp(button3, nil);<br />
                });<br />
            });<br />
        }<br />
        else<br />
        {<br />
            // Masquer (animation rebond) button3, puis button2, puis button1<br />
            bounceViewDown(button3, ^{<br />
                bounceViewDown(button2, ^{<br />
                    bounceViewDown(button1, nil);<br />
                });<br />
            });<br />
        }<br />
    }
    
  • Transposable sur NSView ?

    On est sur le forum Cocoa là  image/tongue.png' class='bbc_emoticon' alt=':P' />
  • AliGatorAliGator Membre, Modérateur
    Arg ! En effet je n'avais pas vu que c'était pour OSX, mea culpa !



    Avec OSX et NSView si on veut la même chose il faut passer par CoreAnimation. Mais bon les propriétés transform et alpha de CALayer ont une animation implicite si je ne m'abuse, non ? Donc l'équivalent pour OSX ne devrait pas être trop méchant non plus ! Après un setWantsLayer:YES sur le bouton, un button1.layer.transform = ... va animer la propriété puisque transform possède une implicit animation. Au pire on peut toujours créer un CAAnimation pour personaliser l'animation image/wink.png' class='bbc_emoticon' alt=';)' />
  • waouh, que de réponses. Je regarde tous ça



    Merci et je vous tiens au courant
  • CéroceCéroce Membre, Modérateur
    'mpergand' a écrit:


    Transposable sur NSView ?


    Oui, en passant par le proxy animator de NSView.
  • Bonjour à  tous



    Je viens de lire avec attention toutes vos propositions.

    Pour répondre à  Karoxys, oui il s'agit bien d'un exemple. C'est plus pour comprendre le principe. De plus c'est quoi un "storyBoard"



    Sinon, mergand, peux tu m'expliquer les "runloop", en allant sur la doc, je dois avouer que je n'ai pas compris grand chose...



    Enfin AliGator, c'est vrai que ta solution semble super mais je vais peut être attendre de maitriser un peu plus, d'autant qu'il semble que sur OSX ça ne semble pas si évident !!



    Merci encore
  • Le storyboard, c'est la nouvelle gestion des view.

    J'utilise pas, mais si j'ai bien capté, comme son nom l'indique, tu crées un " scénario " pour la suite des view...
  • mpergandmpergand Membre
    juillet 2012 modifié #13
    Le storyBoard c'est pour iOS.



    La runloop est le mécanisme de distribution des événements dans Cocoa.



    Par ex, lors de l'appui sur le touche du clavier, cet événement est transmis à  l'application au premier plan, et celle-ci va transmettre ce même événement à  l'objet qui a le focus (first responder) de la fenêtre active.



    La runloop est utilisée par bon nombre de classes comme NSURLDownload, ainsi les données sont reçues via des méthodes delegate sans bloquer l'application, rendant inutile la création d'un thread secondaire.
  • ok merci pour ces info
  • psychoh13psychoh13 Mothership Developer Membre
    août 2012 modifié #15
    Si tu veux faire un fadeIn pour tes boutons, tu peux utiliser des CABasicAnimation avec beginTime de 0.0, 0.3 et 0.6 secondes pour les faire apparaà®tre en décaler.



    Aussi ton utilisation du timer est mauvaise. Il ne faut pas mettre repeat:YES si tu ne veux pas répéter le timer, ce qui est le case ici, tu n'as pas besoin de stocker le timer et de le retain non plus, étant donné que tu ne l'exécutes qu'une fois et qu'il est déjà  retenu par le runloop.



    Tu peux aussi utiliser ce petit gars pour éviter de répartir le code partout: https://gist.github.com/250662



    Exemple:


    <br />
    - (void)displayButtons;<br />
    {<br />
    	[echelle setHidden:NO];<br />
      <br />
    	[NSTimer scheduledTimerWithTimeInterval:0.3 repeats:NO usingBlock:<br />
    	 ^(NSTimer *timer)<br />
    	 {<br />
    		 [ptADigit setHidden:NO];<br />
    	 }];<br />
      <br />
    	[NSTimer scheduledTimerWithTimeInterval:0.6 repeats:NO usingBlock:<br />
    	 ^(NSTimer *timer)<br />
    	 {<br />
    		 [mizeAZero setHidden:NO];<br />
    	 }];<br />
    }<br />
    




    Au passage, la technique avec NSRunLoop complique le problème plus qu'elle ne le résout, tu n'as pas besoin d'aller aussi bas pour exécuter du code comme ça.
  • Merci psychoh13 mais j'ai un warning à  l'exécution : NSTimer' may not respond to '+scheduledTimerWithTimeInterval:repeats:usingBlock:'
  • CéroceCéroce Membre, Modérateur
    Oui, c'est normal, puisque NSTimer n'implemente pas cette méthode.

    C'est pour cela qu'il te dit d'aller télécharger une truc sur github.
Connectez-vous ou Inscrivez-vous pour répondre.