4

FlashとFlexで非常に奇妙な問題が発生しました。特定の状況下では、実行時に(ローダーを使用して)ロードされたSWFからのムービークリップは、その間に別のSWFがロードされた場合にインスタンス化できないようです。エラーを再現するプログラムの完全なコードは次のとおりです。EnsembleTofinoを介してmxmlcを使用してコンパイルされます。

package 
{
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.system.*;

    public class DynamicLoading extends Sprite
    {
        private var testAppDomain:ApplicationDomain;

        public function DynamicLoading()
        {
            var request:URLRequest = new URLRequest("http://localhost/content/test.swf");
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTestLoadComplete);
            loader.load(request);
        }

        private function onTestLoadComplete(e:Event):void
        {
            var loaderInfo:LoaderInfo = LoaderInfo(e.target);
            testAppDomain = loaderInfo.applicationDomain;

            // To get the error, uncomment these lines...
            //var request:URLRequest = new URLRequest("http://localhost/content/tiny.swf");
            //var loader:Loader = new Loader();
            //loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTinyLoadComplete);
            //loader.load(request);

            // ...and comment this one:
            onTinyLoadComplete();
        }

        private function onTinyLoadComplete(e:Event = null):void
        {
            var spriteClass:Class = Class(testAppDomain.getDefinition("TopSymbol"));
            var sprite:Sprite = Sprite(new spriteClass());

            sprite.x = sprite.y = 200;

            addChild(sprite);
        }
    }
}

上記のように2番目の読み込み操作がコメント化されているため、コードは機能します。ただし、2番目のロード操作がコメント化されておらず、2番目のSWFがロードされたnew spriteClass()にonTinyLoadCompleteが実行される場合、次の例外を除いて、を含む行は失敗します。

TypeError:エラー#1034:タイプ強制に失敗しました:flash.display :: MovieClip@2dc8ba1をSubSymbolに変換できません。
    flash.display :: Sprite /constructChildren()で
    flash.display :: Sprite()で
    flash.display :: MovieClip()で
    TopSymbol()で
    DynamicLoading / onTinyLoadComplete()[C:\ Users \ ... \ TestFlash \ DynamicLoading.as:38]で

test.swfとtiny.swfはFlashCS4で作成されました。test.swfには、ActionScript用にエクスポートされた2つのシンボルが含まれています。1つはTopSymbolと呼ばれ、もう1つはSubSymbolと呼ばれます。SubSymbolには単純なグラフィック(落書き)が含まれ、TopSymbolにはSubSymbolの単一のインスタンスが含まれます。tiny.swfには何も含まれていません。これは、新しい空のActionScript3プロジェクトを公開した結果です。

SubSymbolがActionScriptにエクスポートされないようにtest.swfを変更すると、エラーはなくなりますが、実際のプロジェクトでは、他のエクスポートされたスプライトクラスを子として含むスプライトクラスを動的にロードする機能が必要です。

これを引き起こしている原因、またはそれを修正する方法についてのアイデアはありますか?

編集:いくつかの人々は、tiny.swfにtest.swfまたは親(DynamicLoading.swf)のクラスと同じ名前のクラスが含まれている可能性があることを示唆しています。そうではありません。上で述べたように、新しい空のFlash CS4プロジェクトを公開するだけで、自分でtiny.swfを作成しました。swfdump -Dtiny.swfで実行した場合の完全な出力は次のとおりです。

[ヘッダー]ファイルバージョン:10
[ヘッダー]ファイルはzlib圧縮されています。比率:41%
[ヘッダー]ファイルサイズ:1343
[ヘッダー]フレームレート:30.000000
[ヘッダー]フレーム数:1
【ヘッダー】ムービー幅:550.00
[ヘッダー]映画の高さ:400.00
4つのFILEATTRIBUTES as3symbolclass
[04d]1284メタデータ
3セットバックグラウンドカラー(ff / ff / ff)
11シナリオ
[001] 0 SHOWFRAME 1(00:00:00,000)
[000] 0 END
4

4 に答える 4

1

Adobe のドキュメントによると、読み込まれた SWF (TopSymbol など) のシンボル クラスに直接アクセスする場合は、読み込みコンテキストで現在のアプリケーション ドメインを指定する必要があります。したがって、私にとってより大きな問題は、2 番目の読み込みがコメントアウトされた最初の例が機能する理由です。私の唯一の推測は、イベントがの現在のアプリケーション ドメインのcompleteコンテキストで実行されている可能性があるということです。Loader

次のように、test.swf を現在のアプリケーション ドメインに明示的にロードしてみてください。

var context:LoaderContext = new LoaderContext();
context.securityDomain = SecurityDomain.currentDomain;
context.applicationDomain = ApplicationDomain.currentDomain;

var request:URLRequest = new URLRequest("http://localhost/content/test.swf");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTestLoadComplete);
loader.load(request, context);

編集:

動的に読み込まれる SWF が別のアプリケーション ドメインに読み込まれるようにするApplicationDomainため、読み込みごとにオブジェクトを明示的に作成する必要がある場合があります。Loaderデフォルトでアプリドメインが何に使用されているかわかりません。次のようなことを試してください:

public class DynamicLoading extends Sprite
{
    private var testAppDomain:ApplicationDomain;
    private var tinyAppDomain:ApplicationDomain;

    public function DynamicLoading()
    {
        testAppDomain = new ApplicationDomain();
        var context:LoaderContext = new LoaderContext(false, testAppDomain);
        var request:URLRequest = new URLRequest("http://localhost/content/test.swf");
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTestLoadComplete);
        loader.load(request, context);
    }

    private function onTestLoadComplete(e:Event):void
    {
        tinyAppDomain = new ApplicationDomain();
        var context:LoaderContext = new LoaderContext(false, tinyAppDomain);
        var request:URLRequest = new URLRequest("http://localhost/content/tiny.swf");
        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onTinyLoadComplete);
        loader.load(request, context);
    }

    private function onTinyLoadComplete(e:Event = null):void
    {
        var spriteClass:Class = Class(testAppDomain.getDefinition("TopSymbol"));
        var sprite:Sprite = Sprite(new spriteClass());

        sprite.x = sprite.y = 200;

        addChild(sprite);
    }
}    
于 2010-04-03T15:44:46.310 に答える
1

同じ名前のクラスが複数あるため、これは問題のようです。tiny.swf がロードされていない限りコードは機能するので、それが原因だと思いがちです。ライブラリが実際に空であることを確認してください。

于 2010-04-01T09:51:13.097 に答える
1

2 つの swf がロードされたときに、おかしな動作が見られました。この問題は、2 つの swfs に同じクラスの異なるバージョンがある場合に発生します。TopSymbol 内の SubSymbol インスタンスが、直接ロードした SubSymbol と同じであることを確認してください。

于 2010-03-26T20:08:44.383 に答える
1

Adobe のローディング クラスの多くのバグを排除するために、私は絶対に greensock LoaderMax ライブラリを使用します... http://www.greensock.com/loadermax/ シンプルで無料で強力です。

于 2011-02-04T14:12:37.407 に答える