【发布时间】:2017-06-02 15:55:53
【问题描述】:
我创建了一系列 Air Desktop 游戏。在玩游戏之前,用户必须先登录。为了简化操作,我在一个单独的项目中创建了登录系统,并将其保存为名为“dashboard.swf”的 swf 文件。当游戏打开时,它会加载dashboard.swf 并显示登录屏幕。除了登录功能,dashboard.swf 还处理许多其他的东西,比如游戏中的常用设置。
我不想每次对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::CustomEvent@12786a9fed31 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);
}
回答 请参阅下面的@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 文件。
【问题讨论】:
-
您是否在主机 swf 和 dashboard.swf 中都引用了该类 (CustomEvent)?很可能是的,因为根路径不同,安全沙箱也不同,并且您有两个冲突的类,它们实际上是相同的,但并不被视为相同
-
@BadFeelingAboutThis - 我愿意。从 ApplicationDirectory 加载 dashboard.swf 时,它工作正常。当它从 ApplicationStorageDirectory 加载时,我遇到了这个问题。所以实际的代码有效。它与文件的位置有关,我不知道为什么。
-
尝试将您的加载器上下文设置为
currentDomain,就像这里的最后一个示例:help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/… -
您应该添加您的实际解决方案作为答案,然后接受它。这有助于未来的访问者快速获得最相关的信息。
标签: actionscript-3 flash air