2017-06-02 36 views
2

我有一系列我创建的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文件。

+0

你有没有在这两个主机SWF和dashboard.swf阶级(自定义事件)引用?最有可能的是,因为根路径是不同的安全沙箱是不同的,你有两个实际上是相同的,但没有看到相同的冲突类。 – BadFeelingAboutThis

+0

@BadFeelingAboutThis - 我这样做。当从ApplicationDirectory加载dashboard.swf时,它工作正常。这是从ApplicationStorageDirectory加载时,我得到这个问题。所以实际的代码工作。它与文件的位置有关,我无法弄清楚为什么。 – Tony

+0

尝试将加载器上下文设置为'currentDomain',就像这里的最后一个例子:http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7de0.html – BadFeelingAboutThis

回答

2

此错误通常意味着您有来自不同来源的同一个类进入根应用程序。

对于您的情况,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); 
} 

主机CustomEvent了解更多关于装载机背景herehere

+0

谢谢你的解释!但是,现在我遇到了这个问题:SecurityError:错误#2142:安全沙箱冲突:本地SWF文件无法使用LoaderContext.securityDomain属性 – Tony

+0

如果我删除context.securityDomain,则回到原点。我试着从服务器上下载swf文件,将它作为ByeArray保存在ApplicationStorageDirectory中,然后从上下文中加载它。没有运气。然后我试着直接从服务器加载它,并得到同样的问题。 – Tony

+0

当您删除安全域行时是否离开应用程序域?这可能会起作用。所以像这样:'loader.load(yourUrlRequest,新的LoaderContext(false,ApplicationDomain.currentDomain));'或者是你已经尝试过? – BadFeelingAboutThis