actionscript-3 - AS3 Air Desktop - 从 ApplicationStorageDirectory 中的 SWF 调度自定义事件

标签 actionscript-3 flash air

我创建了一系列 Air Desktop 游戏。在玩游戏之前,用户必须首先登录。为了简化操作,我在一个单独的项目中创建了登录系统,并将其保存为名为“dashboard.swf”的 swf 文件。当游戏打开时,它会加载dashboard.swf并显示登录屏幕。除了登录功能之外,dashboard.swf 还处理许多其他内容,例如游戏中的通用设置。

我不想每次更改仪表板.swf 时都重新编译每个游戏。所以,我从服务器下载它。我最初是在 ApplicationDirectory 中下载、保存和加载仪表板.swf,它在 Mac 上运行良好。在 Window 10 上进行测试并进行一些研究后,我发现非 OSX 计算机的 ApplicationDirectory 是只读的。

因此,我将dashboard.swf 的位置更改为ApplicationStorageDirectory。当我在 Mac 上运行它时,swf 加载得很好,但调度的第一个自定义事件会抛出错误:

TypeError: Error #1034: Type Coercion failed: cannot convert com.thisapp.event::CustomEvent@12786a9fed31 to com.thisapp.event.CustomEvent

两个 CustomEvent.as 文件是相同的。当将dashboard.swf 保存到Mac 上的ApplicationDirectory 并从中加载时,它会正常触发。将其移至 ApplicationStorageDirectory 后,我收到此错误。所以我知道这不是实际的自定义调度程序的问题。冒泡是真实的,在 Cancellable 中也是如此。

在这种情况下,什么会导致类型强制失败?

这是我的自定义调度程序:

public class CustomEvent extends Event {

    public static const GOT_RESULT: String = "gotResult";
    public var result: Object;

    public function CustomEvent(type: String, result: Object = null, bubbles: Boolean = false, cancelable: Boolean = false) {
        // constructor code
        super(type, bubbles, cancelable);
        this.result = result;
    }

    public override function clone(): Event {
        return new CustomEvent(type, result, bubbles, cancelable);
    }

}

来 self 的仪表板.swf:

dispatchEvent(new CustomEvent(CustomEvent.GOT_RESULT, null,true,true));

在我的桌面应用程序主类中:

var dashboardURL:String = File.applicationStorageDirectory.url +"dashboard.swf";

  var myContext:LoaderContext = new LoaderContext(); 
myContext.applicationDomain = ApplicationDomain.currentDomain; 
var urlReq:URLRequest = new URLRequest(dashboardURL); 
var ldr:Loader = new Loader();
ldr.load(urlReq, myContext); 
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,loadit);
    function loadit(e:Event){
dashboard = e.target.content as MovieClip;
addChild(dashboard);
dashboard.addEventListener(CustomEvent.GOT_RESULT, runLogin);
}

回答 请参阅下面的 @BadFeelingAboutThis 答案,了解为什么会发生 1034 错误。这是我修复它的方法:

首先 - 从服务器下载 swf(我使用的是 GreenSock 的 LoaderMax):

private function dowloadDashboard(){
    var url:String  = "https://path/to/your/swf/on/the/server.swf";
    var queue:LoaderMax = new LoaderMax({name:"mainQueue",onComplete:completeHandler});
    //Note: the format is set to "binary"
    queue.append( new DataLoader(url, {name:"mySwf",format:"binary", estimatedBytes:3000}) );
    queue.load();

    function completeHandler(event:LoaderEvent):void {
    //Note: "mySwf" is the name I gave to the DataLoader above.
         var b:ByteArray = LoaderMax.getContent("mySwf");
    //loadDashboard() is the next function and I'm passing the ByteArray to it.
        loadDashboard(b);
    }
                }

下一步 - 使用 ByteArray 加载具有正确上下文的 swf:

private function loadDashboard(b:ByteArray) {
var myContext:LoaderContext = new LoaderContext();
        myContext.allowLoadBytesCodeExecution = true;
        myContext.allowCodeImport = true;
        myContext.applicationDomain = ApplicationDomain.currentDomain; 
var ldr:Loader = new Loader();
ldr.loadBytes(b,myContext);
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,loadDone);
}

最后 - 将您的 swf 添加到舞台:

        function loadit(e:Event){
            dashboard = e.target.content as MovieClip;
            addChild(dashboard);
}

我希望这对某人有帮助!请记住,在我的情况下,我有一个 Desktop Air 应用程序,它正在下载并加载服务器上的 swf 文件。

最佳答案

此错误通常意味着相同的类从不同的来源进入您的根应用程序。

在您的情况下,CustomEvent 类必须存在于主机 SWF 文件以及加载的 SWF 文件中。

由于加载的 SWF 与主机 SWF 不在同一应用程序域中,因此 flash/AIR 不会将重叠的类视为同一类。因此,您在 SWF 中加载的 CustomEvent 现在被视为 com.thisapp.event::CustomEvent@12786a9fed31 ,它(尽管完全相同)被视为与 com.thisapp.event 完全不同的类:自定义事件。由于您的代码引用了后者,因此每当来自主机的 CustomEvent 尝试填充类型为 :CustomEvent 的对象引用时,它都会抛出强制错误,因为它们实际上不是同一个类(class)。

通常,解决此问题的方法是指定 context对于加载的 SWF,因此它将加载的类集成到它自己的域中。这应该使用加载的 SWF 的 CustomEvent

覆盖主机 CustomEvent
var ldr:Loader = new Loader();

//The second parameter for load takes a LoaderContext
ldr.load(new URLRequest(File.applicationStorageDirectory.url +"dashboard.swf"), new LoaderContext(false, ApplicationDomain.currentDomain)); 
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE,loadit);

function loadit(e:Event){
    dashboard = e.target.content as MovieClip;
    addChild(dashboard);
    dashboard.addEventListener(CustomEvent.GOT_RESULT, runLogin);
}

了解有关加载器上下文的更多信息 herehere

关于actionscript-3 - AS3 Air Desktop - 从 ApplicationStorageDirectory 中的 SWF 调度自定义事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44333005/

相关文章:

ios - Adobe Air ios 打包程序

actionscript-3 - Flex DRAG_DROP 事件 - 是否可以访问被拖动的图像?

xml - 使用纯 AS3 创建 Android manifest xml

actionscript-3 - 预载声音AS3

新标签(CTRL + T),新窗口(CTRL + N)的javascript?

ios - Adobe Air 3.6 出现阻止备份的问题

algorithm - 扫雷清算算法

actionscript-3 - 如何确定SWF为哪个Flash Player发布?

actionscript-3 - as3 在没有事件的情况下调用事件函数?

air - 自定义俄罗斯方 block 放置算法