4

我在使用 Flash 和 Flex 时遇到了一个非常奇怪的问题。在某些情况下,如果同时加载了另一个 SWF,则在运行时(使用 Loader)加载的 SWF 中的影片剪辑似乎无法实例化。这是重现错误的程序的完整代码。它是通过Ensemble Tofino使用 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);
        }
    }
}

如上所示,将第二个加载操作注释掉后,代码就可以工作了。但是,如果未注释第二个加载操作并且 onTinyLoadComplete第二个 SWF 加载后运行,则包含的行将new spriteClass()失败,并出现以下异常:

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 是在 Flash CS4 中创建的。test.swf 包含两个符号,都为 ActionScript 导出,一个称为 TopSymbol,一个称为 SubSymbol。SubSymbol 包含一个简单的图形(涂鸦),TopSymbol 包含一个 SubSymbol 的实例。tiny.swf 不包含任何内容;这是发布一个新的、空的 ActionScript 3 项目的结果。

如果我修改 test.swf 以便不为 ActionScript 导出 SubSymbol,错误就会消失,但在我们的实际项目中,我们需要能够动态加载包含其他导出 sprite 类作为子项的 sprite 类。

关于造成这种情况或如何解决的任何想法?

编辑:一些人建议 tiny.swf 可能包含一个与 test.swf 或父级 (DynamicLoading.swf) 中的类同名的类。它不是。如上所述,我自己创建了 tiny.swf,只需发布​​一个全新的空 Flash CS4 项目。以下是swfdump -D在 tiny.swf 上运行时的完整输出:

[标题] 文件版本:10
[HEADER] 文件是 zlib 压缩的。比率:41%
[标题] 文件大小:1343
[标题] 帧率:30.000000
[标题] 帧数:1
[标题] 影片宽度:550.00
[HEADER] 影片高度:400.00
[045] 4 文件属性 as3 符号类
[04d] 1284 元数据
[009] 3 背景颜色 (ff/ff/ff)
[056] 11 场景描述
[001] 0 显示帧 1 (00:00:00,000)
[000] 0 结束
4

4 回答 4

1

当加载两个 swfs 时,我看到了时髦的行为。当两个 swf 具有同一类的不同版本时,就会出现问题。检查以确保 TopSymbol 中的 SubSymbol 实例与您直接加载的 SubSymbol 相同。

于 2010-03-26T20:08:44.383 回答
1

根据Adob​​e 的文档,如果您想直接访问加载的 SWF(如 TopSymbol)中的符号类,则应在加载上下文中指定当前应用程序域。所以对我来说,更大的问题是为什么你的第二个加载的第一个例子被注释掉了。我唯一的猜测是该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

为了排除 Adob​​e 加载类中的许多错误,我肯定会使用 greensock LoaderMax 库... http://www.greensock.com/loadermax/ 简单、免费 + 功能强大。

于 2011-02-04T14:12:37.407 回答
1

由于有多个具有相同名称的类,这似乎确实是个问题。由于只要不加载 tiny.swf 代码就可以工作,我倾向于认为这是我们的罪魁祸首。确保库确实是空的。

于 2010-04-01T09:51:13.097 回答