ステージに置いたインスタンスがタイムラインから除かれるときには、DisplayObject.removedFromStageイベント(定数Event.REMOVED_FROM_STAGE)が起こります。ところが、そのインスタンスがTLFテキストを含むと、内部的に初期化が行われるため、一筋縄ではイベントが意図どおりに扱えません。
たとえば、[テキストツール]で[TLFテキスト](インスタンスmy_txt)をひとつつくったMovieClipインスタンスmy_mcがメインタイムラインに置かれたとします(図001)。TLFテキストが新たに備わったFlash Professional CS5の最新Flash Player 10.1で書出すと、メインタイムラインは初めStageオブジェクトの子ではなく、内部的につくられるLoaderインスタンスにロードされます。そして、TLFテキストが初期化された後、改めてStageオブジェクトの表示リストに子として加えられます。
図001■ MovieClipシンボルの中に[TLFテキスト]を置くすると、メインタイムラインをLoaderオブジェクトの表示リストから除くときに、DisplayObject.removedFromStageイベントが送られるのです。つまり、インスタンスをステージから消すときに行うつもりの処理を、TLFテキストの初期化が終わってこれからまさにステージで表示されるべきときに実行してしまうことになります。
さらにたちの悪いことに、最新のCS5.5では動作が変わります。メインタイムラインは初めからStageオフジェクトの子インスタンスとして加えられたまま、もうひとつTLFテキストを初期化するインスタンスがStageオブジェクトの表示リストに加わるのです。つまり、初期化のときインスタンスにDisplayObject.removedFromStageイベントは起こりません。ですから、このイベントは初めの期待どおり、インスタンスがStageオブジェクトを頂点とする表示リストから外れるとき発生します。
問題はFlash Player 10.1でどうやってTLFテキスト初期化時のDisplayObject.removedFromStageイベントを振分けるかです。もちろん、Flash Playerのバージョンを調べるやり方も考えられます。しかし、メインタイムラインつまりインスタンスのDisplayObject.rootプロパティの参照が、Stageオブジェクトの表示リストの子インスタンス(インデックス0)と同じかどうかを確かめればよいでしょう。
以下のスクリプト001は、TLFテキストが含まれたMovieClipシンボルのフレームアクションです。MovieClipインスタンスがDisplayObject.removedFromStageイベントを受取ったとき、リスナー関数(xRemovedFromStage())はStageオブジェクトの子(インデックス0)がメインタイムラインに等しいとき処理を行います。
スクリプト001■DisplayObject.removedFromStageイベントでメインタイムラインがStageオブジェクトの子かどうかを確かめるvar my_txt:TLFTextField; addEventListener(Event.REMOVED_FROM_STAGE, xRemovedFromStage); function xRemovedFromStage(eventObject:Event):void { var childAt0:DisplayObject = stage.getChildAt(0); if (childAt0 == root) { // メインタイムラインがStageオブジェクトの子かどうか removeEventListener(Event.REMOVED_FROM_STAGE, xRemovedFromStage); // 処理内容を書く removeChild(my_txt); // TLFインスタンスを表示リストから除く my_txt = null; // TLFインスタンスの参照を消す } trace(childAt0); }
なお、「予め配置したインスタンスの存在しないフレームに移動しても参照が消えない」と同じ問題を避けるため、TLFテキストのインスタンス(my_txt)はMovieClipインスタンスの表示リストから除き、参照を(nullの代入によって)消しています。