2

所以我有一种情况,我想将一个类的对象从孩子传递给父母说“MyBigAwesomeClass”。我将类定义导入父级和子级。

现在,如果我从相对于父位置的位置加载子 swf,一切都很好,但是当我使用完整的绝对路径加载它时,它会处理父和子中“BigAwesomeClass”的定义作为不同的对象,并且不允许将“BigAwesomeClass”类型的对象分配给父类中相同的对象。

我完全被难住了,并且在ApplicationDomains上猛烈抨击,包括使用这段代码

loader.contentLoaderInfo.addEventListener(Event.COMPLETE,swfLoaded);
var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); 
loader.load(new URLRequest(_file.url),context);

完全无济于事。关于我能做些什么来解决这个问题的任何想法?

提前致谢

4

4 回答 4

1

根据 Adob​​e 的文档(Loader#securityDomain):

为了导入加载成功,加载的 SWF 文件的服务器必须有一个信任加载 SWF 文件域的策略文件。

诀窍是告诉 Loader 在加载 swf 时检查跨域文件,true方法是在创建时作为第一个参数传递LoaderContext,例如:

var request:URLRequest = new URLRequest(_file.url);
var context:LoaderContext = new LoaderContext(true, null, SecurityDomain.currentDomain);
var loader:Loader = new Loader();
loader.load(request, context);

随附的 cross-domain.xml 应位于与子 SWF 相同的位置,或者位于其父文件夹之一中。根据 Adob​​e 的文档,这是一个非限制性的跨域文件

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM
"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
    <site-control permitted-cross-domain-policies="all"/>
    <allow-access-from domain="*" secure="false"/>
    <allow-http-request-headers-from domain="*" headers="*" secure="false"/>
</cross-domain-policy>

另一件可能使您更容易的事情是传递接口而不是类,这将有效地绕过冲突代码。这将起作用,因为默认情况下,子类在运行时从父类继承接口(参见Loader#applicationDomain point #1)。只要该对象遵守接口,子类就可以安全地实例化它自己的每个对象版本。例如:

var applicationDomain:ApplicationDomain = loader.contextLoaderInfo.applicationDomain;
var classDefinition:Class = applicationDomain.getDefinition("MyBigAwesomeClass") as class;
var instance:IMyBigAwesomeInterface = new classDefinition() as IMyByAwesomeInterface;

MyBigAwesomeClass 的定义将如下所示:

public class MyBigAwesomeClass implements IMyBigAwesomeInterface 
{
    ...
}
于 2011-08-13T14:19:30.930 回答
1

好吧,事实证明它是一个沙盒问题。不属于安装程序的文件被放置在不同的安全沙箱中,并且由于它们位于不同的沙箱中,当导入到父级时,子级不会继承其父级的定义,ApplicationDomain并且存在两个不兼容的独立定义。可悲的是,似乎没有直接的方法可以解决这个问题。Adobe 确实允许通过SandBoxBridge在沙箱之间进行通信,但这会迫使您使用 Object 类型,这违背了整个事情的目的。据我所知,两个不同沙箱中的类无法兼容,即使它们完全相同。我想它回到了没有严格键入对象的痛苦世界。

于 2011-08-14T12:20:38.787 回答
0

我同意你的观点,这个问题可能与父母和孩子的应用程序域有关,但为了更准确地回答,最好有一些你想在父母和孩子之间共享的类的示例使用孩子。

从理论上讲,如果也为孩子定义了一个类,似乎可以避免这个问题......这是一个非常基本的例子,在我看来,无论你从哪里加载孩子,它都应该可以工作。

包 com.example.test
{
   公共类父扩展雪碧
   {
      私人 var child:孩子;
      私有 var shared:SharedClass = new SharedClass();

      公共函数父()
      {
         加载孩子();
      }

      私有函数 loadChild():void
      {
         // 加载过程
      }

      私有函数加载完成(事件:事件):无效
      {
          child = event.currentTarget.content 作为孩子;

          如果(孩子!=空)   
             共享 = child.shared;
          // 删除事件等...
      }
   }
}

包 com.example.test
{
   公共类子扩展雪碧
   {
      // 我在这里使用公共变量,但你可以使用 getter...
      公共变量共享:SharedClass;

      公共功能儿童()
      {
            共享 = 新的 SharedClass();
      }
   }
}

包 com.example.test
{
   公共类 SharedClass
   {
      公共函数 SharedClass()
      {
           trace('来自共享类的你好');
      }
   }
}
于 2011-08-13T16:50:33.757 回答
0

一种选择是在子类中实现一个方法,以使用它自己的应用程序域返回该类的实例,例如:

public class Child extends Sprite implements IMyBigAwesomeClassLoader
{
   public function getMyByigAwesomeClass():IMyBigAwesomeClass
   {
       var classDefinition:Class = applicationDomain.getDefinition("MyBigAwesomeClass");
       var instance:IMyBigAwesomeClass = new classDefinition() as IMyBigAwesomeClass;
       return instance;
   }
}

IMyBigAwesomeClassLoader看起来像这样:

public interface IMyBigAwesomeClass 
{
  function getMyBigAwesomeClass():IMyBigAwesomeClass;
}

然后,父剪辑将使用它在加载时从子剪辑获取实例:

public function loadCompleteHandler(event:Event):void
{
  var myBigAwesomeClassLoader:IMyBigAwesomeClassLoader = (event.target as Loader).content as IMyBigAwesomeClass;
  myBigAwesomeClass = myBigAwesomeClassLoader.getMyBigAwesomeClass();
}

这里使用接口的原因是将类定义与其实现分离。尽管父 SWF 和子 SWF 中的类具有相同的名称,但 Flash 将它们视为不同的类。该界面告诉Flash,即使它们不同,它们也可以以相同的方式使用。

Flash 使用静态类型,这意味着一旦定义了一个类,它就永远不会改变,这意味着它永远不会用另一个类定义覆盖一个类定义。所以如果有两个同名的类,就要用它getDefinition来解决冲突的名字。如果您想避免这种增加的复杂性,您可以为父 SWF 和子 SWF 中的类使用不同的名称或名称空间。

于 2011-08-14T10:32:29.573 回答