サイトトップ

Director Flash 書籍 業務内容 プロフィール

Macromedia Flash非公式テクニカルノート

Flash Player 10で予め配置したMovieClipのないフレームに移動したときイベントリスナーがすぐに消える

ID: FN1011003 Product: Flash CS5 and above Platform: All Version: 9 and above/ActionScript 3.0

問題
予めタイムラインに置いたMovieClipインスタンスに登録したイベントリスナーは、インスタンスのないフレームに移動しても通常直ちには消えません。ガベージコレクションが働いてメモリを解放するまで待たなければならないからです(「予め配置したMovieClipのリスナーがインスタンスのないフレームに移動してもイベントを受取る」参照)。ところが、Flash Player 10では、MovieClipインスタンスのないフレームに入った途端にイベントは受取られなくなることがあります。

たとえば、メインタイムラインに2フレームをつくり、その第1フレームのみに空のMovieClipインスタンスを置きます(図001)。MovieClipシンボル内にスクリプトは書きませんし、とくにビジュアルエレメントもなくて構いません。インスタンス名はmy_mcとします。

図001■全2フレームのメインタイムライン第1フレームにMovieClipインスタンスを置く
図001左図 図001右図

MovieClipインスタンスを置いたメインタイムラインの第1フレームに、以下のスクリプト001を書きます(図002)。フレームアクションは、MovieClipインスタンスmy_mcのDisplayObject.enterFrameイベント(定数Event.ENTER_FRAME)にリスナー関数(xTest())を登録しています。

そして、リスナー関数は、メインタイムラインの現行フレームと子インスタンスの数、およびインスタンスに設定した変数(id)の値を[出力]します。この変数値はgetTimer()関数が返す整数で、インスタンスを識別するために設定しています(前掲「予め配置したMovieClipのリスナーがインスタンスのないフレームに移動してもイベントを受取る」参照)。

スクリプト001■メインタイムラインからMovieClipインスタンスにイベントリスナーを登録

// フレームアクション: メインタイムライン
// MovieClipインスタンスmy_mcを配置
var my_mc:MovieClip;
my_mc.id = String(getTimer());
my_mc.addEventListener(Event.ENTER_FRAME, xTest);
function xTest(eventObject:Event):void {
  var _mc:MovieClip = MovieClip(eventObject.currentTarget);
  trace(currentFrame, numChildren, _mc.id);
}

図002■メインタイムラインに第1フレームアクションを記述
図002

[ムービープレビュー]を確かめると、[出力]パネルには何も表示されません。つまり、イベントリスナーが呼ばれていないようです。もちろん、DisplayObject.enterFrameイベントが発生する第2フレームには、MovieClipインスタンスがありません。インスタンスがなくなれば、イベントリスナーもともに消えることになります。

ただし、前述のとおりイベントリスナーを消すのは、ガベージコレクションの役目です。参照がなくなったからといって、ガベージコレクションは直ちに働く訳ではありません。詳しくは、前述「予め配置したMovieClipのリスナーがインスタンスのないフレームに移動してもイベントを受取る」で解説しました。


原因
別のノート「タイムラインに置いたMovieClipからフレーム移動するとrootやstageが参照できない」で検討したように、タイムラインに配置したインスタンスのふるまいはFlash Player 10で少し変わった節があります。[パブリッシュ設定]で[Player]のバージョンをFlash Player 9に変えると、[ムービープレビュー]で[出力]が現れます(図003)。

図003■[パブリッシュ設定]でFlash Player 9に変えると[出力]が表れる
図003上図

図003下図

[出力]からは、子インスタンスの数が第1フレームは1で第2フレームが0であるにも拘らず、イベントリスナーの数が増えていく理由は、前掲「予め配置したMovieClipのリスナーがインスタンスのないフレームに移動してもイベントを受取る」で説明しています。


対処法
Flash Player 9と10のふるまいを同じにするには、ふたつ方法があるようです。

[1] MovieClipシンボルのフレームに何か書く
MovieClipシンボルのフレームに何かを書きます。スクリプトでなくても、コメント行区切り記号//ひとつで構いません。Flash Player 10でも[出力]が表れます。

[2] MovieClipインスタンスへの参照をなくす
逆にFlash Player 9でも、MovieClipインスタンスへの参照をすべてなくせば、リスナー関数がイベントを受取らなくなるようです。前掲スクリプト001を例にとるなら、フレームアクションの終わりに、MovieClipインスタンスが納められた変数にnullを代入します。

// フレームアクション: メインタイムライン
// MovieClipインスタンスmy_mcを配置
var my_mc:MovieClip;
my_mc.id = String(getTimer());
my_mc.addEventListener(Event.ENTER_FRAME, xTest);
function xTest(eventObject:Event):void {
  var _mc:MovieClip = MovieClip(eventObject.currentTarget);
  trace(currentFrame, numChildren, _mc.id);
}
my_mc = null;   // 追加

この結果から、Flash Player 10で加えられたのは、MovieClipインスタンスへの参照を暗黙的に破棄する処理ではないかと推測されます。


作成者: 野中文雄
作成日: 2010年11月5日


Copyright © 2001-2010 Fumio Nonaka.  All rights reserved.