そんな訳でProgression Frameworkの話。つか、何で俺だけこんなに沢山の問題にぶち当たるのだろうか?やはり開発スタイル間違ってるのか?
さて今回は、ForLoopコマンドでDoTweener実行しようとしたらスタックオーバーフローで死ぬって話。
■問題と原因
この理由は案外簡単で、実はForLoop使わなくても、多分DoTweener再利用しようとしたら発生すると思う。
原因になってる、DoTweenerのコードはこの部分。
- /*======================================================================*//**
- * @inheritDoc
- * @langversion 3.0
- * @playerversion Flash 9.0.45.0
- *//*=======================================================================*/
- protected override function _executeProgress():void {
- // 既存のイベントハンドラメソッドを保存する
- _onCompleteFunction = tweeningParameters.onComplete;//・・・・・・・(1)-1
- // イベントハンドラメソッドを登録する
- tweeningParameters.onComplete = _onComplete;//・・・・・・・(1)-2
- // アニメーションを開始する
- if ( !Tweener.addTween( _target, _tweeningParameters ) ) {
- // 処理を終了する
- _executeComplete();
- }
- }
- /*======================================================================*//**
- *
- * @langversion 3.0
- * @playerversion Flash 9.0.45.0
- *//*=======================================================================*/
- private function _onComplete():void {
- // Tweener に設定されていた onComplete() メソッドを実行する
- if ( _onCompleteFunction is Function ) {
- _onCompleteFunction.apply( null );//・・・・・・・(2)
- }
- // 処理を終了する
- _executeComplete();
- }
(1)と(2)は俺が入れたんだけど、この2箇所のコードがポイント。
処理の流れを追うと、
- DoTweenerコマンドが始まると、元々Tweenerに渡す予定だった
onComplete
関数を_onCompleteFunction
に退避して((1)-1)、 - 代わりにDoTweenerの終了処理に入れてる((1)-2)。
こうする事で、Tweenerの処理が終わった後呼ばれるのが、DoTweenerコマンドで定義されてる_onComplete()
になる。
で、
- DoTweenerの終了処理で、
_onComplete
関数が呼ばれる。 _onComplete
関数の中で元々の終了処理である_onCompleteFunction()
を実行する。
でまぁ、DoTweenerの処理は滞りなく終了するわけだけど、ここで大きな異変が。
(1)-2の部分で、Tweener用のパラメータが最初とは違うものになっちゃってる。わけです。
具体的に言うとonComplete
。こいつが_onComplete
関数になっちゃってるから、次にもう一回このDoTweenerコマンドを使うとどうなるか?
処理の流れを追うと、
- DoTweenerコマンドが始まると、元々Tweenerに渡す予定だった
onComplete
関数を_onCompleteFunction
に退避して((1)-1)、 - 代わりにDoTweenerの終了処理に入れてる((1)-2)。
- DoTweenerの終了処理で、
_onComplete
関数が呼ばれる。 _onComplete
関数の中で元々の終了処理である_onCompleteFunction()
を実行する。- が、2回目の「元々の終了処理」は
_onComplete
関数であるため、_onComplete
関数が実行される。 _onComplete
関数の中で元々の終了処理である_onCompleteFunction()
を実行する。_onCompleteFunction
関数である、_onComplete
関数が実行される。_onComplete
関数の中で元々の終了処理である_onCompleteFunction()
を実行する。_onCompleteFunction
関数である、_onComplete
関数が実行される。
・・・
こんな感じで無限に_onComplete()
が呼ばれ続け、最終的にはスタックオーバーフローで終了。
■解決策
DoTweener#_onComplete
を以下のように修正。
- private function _onComplete():void {
- // Tweener に設定されていた onComplete() メソッドを実行する
- if ( _onCompleteFunction is Function ) {
- _onCompleteFunction.apply( null );
- }
- //onCompleteを元に戻す。
- tweeningParameters.onComplete = _onCompleteFunction;
- _onCompleteFunction = null;
- // 処理を終了する
- _executeComplete();
- }
要するに、「終了時には元に戻しましょう」ということでいいと思う。でも成功確認しかしてないけど。
最新コメント