我遇到了Flash和Flex的一个非常奇怪的问题。看来在某些情况下,如果在同一时间加载了另一个SWF,则无法在运行时(使用Loader)加载的SWF中的影片剪辑被实例化。以下是重现错误的程序的完整代码。它是使用mxmlc编译的,通过Ensemble Tofino:
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);
}
}
}
如上所示注释掉第二个加载操作,代码可以工作。但是,如果第二个加载操作未注释并且onLinyLoadComplete在加载第二个SWF后运行,则包含new spriteClass()
的行将失败,并出现以下异常:
TypeError: Error #1034: Type Coercion failed: cannot convert flash.display::MovieClip@2dc8ba1 to SubSymbol. at flash.display::Sprite/constructChildren() at flash.display::Sprite() at flash.display::MovieClip() at TopSymbol() at 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,则错误消失,但在我们的实际项目中,我们需要能够动态加载包含其他导出精灵类作为子节点的精灵类。
有关导致此问题的原因或如何解决问题的任何想法?
编辑:有几个人建议tiny.swf可以包含一个与test.swf或父类(DynamicLoading.swf)中的类同名的类。 它没有。正如我上面所说,我通过简单地发布一个全新的空Flash CS4项目来创建tiny.swf。以下是在tiny.swf上运行时swfdump -D
的完整输出:
[HEADER] File version: 10 [HEADER] File is zlib compressed. Ratio: 41% [HEADER] File size: 1343 [HEADER] Frame rate: 30.000000 [HEADER] Frame count: 1 [HEADER] Movie width: 550.00 [HEADER] Movie height: 400.00 [045] 4 FILEATTRIBUTES as3 symbolclass [04d] 1284 METADATA [009] 3 SETBACKGROUNDCOLOR (ff/ff/ff) [056] 11 SCENEDESCRIPTION [001] 0 SHOWFRAME 1 (00:00:00,000) [000] 0 END
答案 0 :(得分:1)
当加载两个swfs时,我看到了时髦的行为。当两个swfs具有相同类的不同版本时,会出现问题。检查以确保TopSymbol中的SubSymbol实例与您直接加载的SubSymbol相同。
答案 1 :(得分:1)
由于有多个具有相同名称的类,这看起来似乎有问题。由于代码只要tiny.swf没有加载就可以工作,我倾向于认为这是我们的罪魁祸首。确保库确实是空的。
答案 2 :(得分:1)
根据Adobe's documentation,如果要直接访问已加载的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);
}
}
答案 3 :(得分:1)
为了排除Adobe的加载类中的许多错误,我肯定会使用greensock LoaderMax库... http://www.greensock.com/loadermax/ 简单,自由+强大。