AS3 Air Desktop - 从SWF中调度ApplicationStorage目录中的自定义事件
我有一系列我创建的Air Desktop游戏。在玩游戏之前,用户必须先登录。为了简化事情,我在一个单独的项目中创建了登录系统,并将其保存为名为“dashboard.swf”的swf文件。游戏打开时,会加载dashboard.swf并显示登录屏幕。除了登录功能外,dashboard.swf还处理一系列其他内容,例如游戏中的常用设置。AS3 Air Desktop - 从SWF中调度ApplicationStorage目录中的自定义事件
我不想在每次更改dashboard.swf时重新编译每个游戏。所以,我从服务器下载它。我最初是在ApplicationDirectory中下载,保存和加载dashboard.swf,并且它在Mac上运行良好。在Window 10上测试并做了一些研究之后,我发现非OSX机器的ApplicationDirectory是只读的。
因此,我将dashboard.swf的位置更改为ApplicationStorageDirectory。当我在我的Mac上,SWF文件加载就好运行它,但被分派第一个自定义事件抛出和错误:
TypeError: Error #1034: Type Coercion failed: cannot convert com.thisapp.event::[email protected] to com.thisapp.event.CustomEvent
两个CustomEvent.as文件是相同的。当dashboard.swf保存到Mac上的ApplicationDirectory并从其加载时,它会很好地启动。一旦我将它移动到ApplicationStorageDirectory,我得到这个错误。所以我知道这与实际的自定义调度程序不是问题。起泡是真的,所以在可取消。
在这种情况下会导致类型强制失败?
这里是我的自定义调度:
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);
}
}
从我dashboard.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);
}
ANSWER 见@ BadFeeling关于这个答案在下面给unde rstand为什么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);
}
我希望帮助别人!请记住,在我的情况下,我有一个桌面空气应用程序正在下载并加载服务器上的swf文件。
此错误通常意味着您有来自不同来源的同一个类进入根应用程序。
对于您的情况,CustomEvent
类必须同时存在于主机SWF文件以及加载的SWF文件中。
由于加载的SWF与主机SWF不在同一个应用程序域中,因此flash/AIR不会将重叠的类视为同一类。所以你加载SWF的CustomEvent现在被看作com.thisapp.event::[email protected]
哪个(尽管完全一样)被认为是完全不同的类,而不是com.thisapp.event:CustomEvent
。由于您的代码引用了后者,因此主机的CustomEvent
任何时候都会尝试将其填入对象引用类型:CustomEvent
中,因为它们实际上并不是相同的类,所以会引发强制错误。
通常,解决此问题的方法是为加载的SWF指定context,以便将加载的类整合到其自己的域中。这应该覆盖与加载的SWF的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);
}
谢谢你的解释!但是,现在我遇到了这个问题:SecurityError:错误#2142:安全沙箱冲突:本地SWF文件无法使用LoaderContext.securityDomain属性 – Tony
如果我删除context.securityDomain,则回到原点。我试着从服务器上下载swf文件,将它作为ByeArray保存在ApplicationStorageDirectory中,然后从上下文中加载它。没有运气。然后我试着直接从服务器加载它,并得到同样的问题。 – Tony
当您删除安全域行时是否离开应用程序域?这可能会起作用。所以像这样:'loader.load(yourUrlRequest,新的LoaderContext(false,ApplicationDomain.currentDomain));'或者是你已经尝试过? – BadFeelingAboutThis
你有没有在这两个主机SWF和dashboard.swf阶级(自定义事件)引用?最有可能的是,因为根路径是不同的安全沙箱是不同的,你有两个实际上是相同的,但没有看到相同的冲突类。 – BadFeelingAboutThis
@BadFeelingAboutThis - 我这样做。当从ApplicationDirectory加载dashboard.swf时,它工作正常。这是从ApplicationStorageDirectory加载时,我得到这个问题。所以实际的代码工作。它与文件的位置有关,我无法弄清楚为什么。 – Tony
尝试将加载器上下文设置为'currentDomain',就像这里的最后一个例子:http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7de0.html – BadFeelingAboutThis