サイトトップ

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

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

コールバック関数からMovieClipを削除するとonUnloadが呼出されない

ID: FN0510006 Product: Flash

Platform: All
Version: MX 2004 and 8

問題
Flash MX 2004およびFlash 8で確認されました。MovieClip.removeiMovieClip()メソッドでインスタンスを削除したり、MovieClipの存在しないフレームに移動すると、そのインスタンスに設定したMovieClip.onUnloadイベントハンドラメソッドが呼出されます。ところが、setInterval()関数などに設定したコールバック関数内でMovieClipを削除すると、そのインスタンスに設定したMovieClip.onUnloadイベントが呼出されません(スクリプト001)。

スクリプト001■setInterval()のコールバック関数からMovieClipを削除するテスト

// タイムライン: _root
// フレームアクション
// MovieClipインスタンス_root.my_mcをこのフレームにのみ配置
var my_mc:MovieClip;
my_mc.onUnload = function():Void {
  trace("unload");
};
var nID:Number = setInterval(xClearMovieClip, 1000);
function xClearMovieClip():Void {
  // my_mc.unloadMovie();   // [1] onUnloadが呼出される
  // my_mcはつぎのフレームには存在せず
  // _root.nextFrame();   // [2] onUnloadは呼出されず
  my_mc.swapDepths(1);   // [3] 削除するため正の深度に移動
  my_mc.removeMovieClip();   // [4] onUnloadは呼出されず
  clearInterval(nID);
  trace(my_mc);   // コールバック関数の呼出し確認用
}
this.stop();

MovieClip.removeMovieClip()メソッドによらず、インスタンスの存在しないフレームに移動した場合(スクリプト001の[2]を有効にして[3][4]をコメントアウト)も、やはりMovieClip.onUnloadイベントは発生しません。MovieClip.unloadMovie()メソッドでコンテンツをクリアした場合(スクリプト001の[1]を有効にして[3][4]をコメントアウト)には、MovieClip.onUnloadイベントハンドラメソッドは呼出されます。ただし、それに続けてMovieClip.removeMovieClip()メソッドを使用(スクリプト001の[3][4]を有効に)すると、やはりMovieClip.onUnloadは呼ばれなくなります。

原因
setInterval()関数あるいはLoadVarsやXML、XMLSocketクラスのonData/onLoadイベントハンドラメソッドに設定したコールバック関数内でMovieClipを削除すると、そのインスタンスに設定したMovieClip.onUnloadイベントハンドラメソッドは呼出されないようです[*1]。

フレームアクションやMovieClip/Buttonのイベントハンドラアクションから削除した場合には、問題なくMovieClip.onUnloadイベントは発生します。また、MovieClipやButtonにイベントハンドラメソッドを設定して、そのコールバック関数から削除した場合も問題ありません。

[*1] この問題についての報告や議論は、FLASH-japan「MovieClip.onUnload のバグ?」、LiveDocs「MovieClip.onUnload」、[Flashcoders]「Serious Player Bug: onUnload event does not fire in callbacks 」をご参照ください。

対処法
問題のあるコールバック関数内で直接インスタンスを削除せず、正しく動作するMovieClipのイベントハンドラなどに移行して処理を行えばよいでしょう。たとえば、MovieClip.onEnterFrameイベントハンドラメソッドでインスタンスを削除すれば、MovieClip.onUnloadイベントは発生します(スクリプト002)。

スクリプト002■MovieClip.onEnterFrameハンドラに処理を移してインスタンスを削除

// タイムライン: _root
// フレームアクション
// MovieClipインスタンスを作成
var my_mc:MovieClip = this.createEmptyMovieClip("test_mc", 1);
my_mc.onUnload = function():Void {
  trace("unload");
};
var nID:Number = setInterval(xClearMovieClip, 1000);
function xClearMovieClip():Void {
  my_mc.onEnterFrame = function() {
    this.swapDepths(1);
    this.removeMovieClip(); // onUnloadは呼出される
  };
  clearInterval(nID);
  trace(my_mc);
}

_____

作成者: 野中文雄
作成日: 2005年10月18日


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