Il est temps pour un autre conseil rapide de débogage. Nous allons continuer à nous concentrer sur les erreurs spécifiques (et communes) qui ont tendance à bloquer les ActionScripters moins expérimentés. Dans ce cas, nous allons couvrir l'erreur # 1063, l'erreur d'incompatibilité de comptage d'arguments.
Tout d'abord, créons une situation où l'erreur se produit. Ouvrez un nouveau document Flash (en supposant que vous suiviez Flash Pro CS3 +, sinon cet exemple est facilement adapté à un projet Flex). Ouvrez l'éditeur de script et entrez le code suivant:
import flash.events.MouseEvent; function onClick (): void trace ("click."); stage.addEventListener (MouseEvent.CLICK, onClick);
Vous pouvez probablement déjà détecter le problème. Si vous avez passé du temps à écrire ActionScript 3, vous vous êtes déjà retrouvé à écrire des gestionnaires d'événements. Si non, ne vous sentez pas mal à l'aise - nous reviendrons sur tout cela en temps voulu.
Si vous exécutez le fichier Flash tel quel, puis cliquez sur la scène, vous obtiendrez le message d'erreur d'exécution suivant:
ArgumentError: Erreur n ° 1063: Incompatibilité du nombre d'arguments dans Untitled_fla :: MainTimeline / onClick (). Attendu 0, a obtenu 1.
Et nous n'arrivons jamais à la déclaration de trace qui devrait ont couru après avoir cliqué.
Alors que se passe-t-il? Dans ce cas, le verbiage d’Adobe concernant l’erreur n’est pas si grave, et si vous avez pris l’habitude d’analyser un message d’erreur au moment de l’exécution, sa signification est peut-être assez claire. Mais tout le monde n'est pas aussi intelligent que vous, alors voici la répartition pour tous les autres.
ArgumentError -- C’est une information quelque peu inconséquente, mais elle montre la spécificité Erreur
classe qui a été jeté. Nous avons quelque chose qui n'est pas aussi général qu'un simple Erreur
, et nous avons entré une catégorisation d'erreur spécifique associée aux arguments (aux fonctions et méthodes).
Erreur n ° 1063 -- Ici, nous donnons simplement le numéro d'erreur formel, comme toutes les bonnes erreurs d'exécution. Vous pouvez utiliser ce code pour le localiser plus facilement dans la documentation sur les erreurs d'exécution d'Adobe..
Incohérence dans le décompte? -- En termes plus prolétariens, le nombre d'arguments envoyés à une fonction était erroné. Quelle fonction? Ses?
? sur Untitled_fla :: MainTimeline / onClick (). -- Ceci identifie simplement la fonction qui a reçu un nombre incorrect d'arguments.
Attendu 0, a obtenu 1. -- Nous obtenons quelques informations supplémentaires dans cette description d'erreur. Ceci détaille l'inadéquation du nombre. Cette phrase changera en fonction de la nature de l'erreur spécifique, mais dans notre cas, cela signifie que la fonction a été écrite sans aucun argument dans la signature, mais qu'un seul argument lui a été envoyé de toute façon..
Flash aime ses canards d'affilée. Alors, il remarque cette divergence et décide de jeter un colère erreur, car il préférerait que vous (le développeur) sachiez ce qui ne va pas, plutôt que de simplement ignorer le problème. C'est bien, parce que si l'inadéquation du décompte allait dans l'autre sens (1 attendu, 0), nous serions bloqués sans argument pour un paramètre requis, et la fonction ferait ce que chien sait..
La nature de l’erreur devrait être claire à ce stade, mais vous pouvez toujours vous demander pourquoi elle s’est produite. D'où vient cet argument superflu?
L'argument n'est pas vraiment superflu. En fait, c'est attendu, puisque nous avons associé notre fonction à un écouteur d'événement. Le système d’événement en Flash a la notion de objet événement qui encapsule des aspects de l'événement qui s'est produit. Cet objet est transmis à la fonction d'écoute comme unique argument. Alors on attendu 0 parce que nous avons écrit notre fonction sans aucun paramètre, mais nous a 1 parce que le répartiteur d'événements a envoyé un objet événement.
Maintenant, vous vous demandez peut-être pourquoi le compilateur n'a pas détecté cette erreur. C'est vrai: si vous avez écrit ceci:
fonction sayClick (): void trace ("click."); sayClick (42);
Ensuite, le fichier SWF ne sera même pas compilé, car vous obtiendrez cette erreur:
1137: Nombre d'arguments incorrect. Attendu pas plus que 0.
La différence est que dans le dernier exemple, nous avons un code qui appelle la fonction avec un nombre incorrect d'arguments. C'est-à-dire que nous avons écrit la ligne qui appelle la fonction de manière incorrecte. Le compilateur peut regarder la ligne qui définit la fonction et la ligne qui appelle la fonction, les comparer pour détecter les divergences et sonner l'alarme lorsqu'elles se produisent..
Cependant, dans l'exemple d'origine, aucune ligne de code écrite n'appelle littéralement la fonction par son nom. Au lieu de cela, la fonction est appelée par référence. Lorsque nous ajoutons l'écouteur d'événement, nous transmettons la fonction. À ce stade, il s'agit d'une variable et non d'un appel de fonction. Cette référence est stockée par le répartiteur d'événements, puis exécutée dynamiquement lorsque l'événement se produit (il s'agit d'une vue d'ensemble de haut niveau sur le fonctionnement du système d'événements, mais nous n'avons pas le temps d'aller plus en profondeur). Ainsi, la ligne de code qui appelle finalement la fonction à l'origine des erreurs est une ligne de code plutôt générique qui utilise l'indirection pour effectuer le travail, ce qui rend le compileur beaucoup plus difficile à intercepter..
(À mon avis, Adobe pourrait au moins enregistrer le addEventListener
ligne au moment de la compilation et allez à la recherche de la fonction par son nom. S'il trouve une correspondance, il pourrait vérifier la signature de la fonction pour un argument d'événement approprié et générer des erreurs en conséquence. Cela ne peut toujours pas être fait de manière infaillible, mais cela pourrait vous aider à résoudre ces erreurs avant d'exécuter le fichier SWF..
Le point principal, cependant, est que cette erreur d'exécution a un équivalent au moment de la compilation, mais que l'erreur d'exécution se produit lorsque la fonction est appelée par référence et non directement par nom..
La pluie commence à tomber lorsque nous appelons la fonction par référence et que nous avons une différence dans le nombre d'arguments. Nous avons généralement deux options: nous pouvons modifier l'appel ou modifier les arguments de la fonction. Dans cet exemple particulier, nous ne pouvons pas modifier l'appel, car cela se produit à l'intérieur EventDispatcher
, code auquel nous n'avons pas accès. Cela nous laisse avec la modification des arguments.
Ceci, encore une fois, a deux options. Tout d'abord, nous pouvons simplement ajouter l'argument. Cela aligne le nombre d'arguments et à partir de maintenant, tout sera copacétique. Nous n'avons pas besoin d'utiliser l'argument, nous avons juste besoin de la fonction? Catch? quand on l'appelle.
fonction onClick (e: MouseEvent): void
La deuxième option consiste, encore une fois, à ajouter l’argument (ce n’est pas grave, j'en ai bien peur). Toutefois, si vous avez initialement écrit la fonction en tant que fonction standard et non en tant qu'écouteur d'événements, et que vous l'appelez ailleurs dans votre code sans arguments, vous pouvez apprécier cette variation. Rendre l'argument facultatif et le mettre par défaut à nul
:
fonction onClick (e: MouseEvent = null): void
Cela fonctionnera bien avec le système d’événements: il recevra un objet événement et pourra le récupérer. Cela fonctionne également bien avec votre code existant; si aucun argument n'est envoyé, le paramètre default est utilisé et la fonction continue.
Notez que cette erreur ne se limite pas aux écouteurs d'événement, bien que ce soit probablement le contexte le plus courant dans lequel vous le rencontrerez. En fin de compte, c'est l'utilisation de fonctions stockées dans des variables, par opposition à celles appelées par leur nom, qui conduit à l'erreur. Voici comment fonctionne le système d’événement. Nous pouvons retravailler l'exemple original pour produire plus ou moins la même erreur, mais sans le clic:
fonction sayMyName (name: String): void trace ("Hello," + name); var funcRef: Function = sayMyName; funcRef ();
Encore une fois, l’erreur du compilateur est dépassée car nous avons une couche d’indirection entre la définition de la fonction et l’appel de la fonction. Ainsi, nous obtenons l'erreur d'exécution (attendu 1, obtenu 0).
Ce n'est pas toujours cette coupe et sec, cependant. Si vous utilisez des rappels dans votre code, vous risquez de tomber dans l'erreur 1063. Les rappels sont un peu comme des écouteurs d'événement, mais il n'existe aucun mécanisme intégré formel pour les implémenter. Ce sont essentiellement des fonctions que vous transmettez par référence, qui sont stockées (temporairement ou à long terme) par un autre processus, qui appelle ensuite la fonction de rappel au moment opportun..
Les moteurs de interpolation les implémentent généralement. Certains optent pour un système piloté par les événements plus formel, mais TweenLite, par exemple, utilise des rappels pour recevoir des notifications concernant la progression de l'interpolation. Cette ligne:
TweenLite.to (someClip, 1, onComplete: tweenFinished, onCompleteParams: [42, "answer"]);
? appellerait une fonction nommée tweenFinished
à la fin de l'interpolation, en passant deux paramètres à la fonction. Cette technique est finalement plus flexible que les événements, car vous n'êtes pas limité à un seul objet événement en tant que paramètre. Cependant, elle se prête à des vulnérabilités similaires à l’erreur 1063 en raison de la nature des fonctions de transfert par référence.
Cela met fin à un autre conseil rapide de débogage. Merci d'avoir lu et j'espère que vous avez appris quelque chose en cours de route!