【问题标题】:Share Classes between Parent and Child SWF在父子 SWF 之间共享类
【发布时间】:2011-10-26 09:52:39
【问题描述】:

所以我有一种情况,我想将一个类的对象说“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);

完全没有用。 关于我可以做些什么来解决这个问题的任何想法?

提前致谢

【问题讨论】:

  • 当您创建子 SWF 时,您是否针对父 swf 进行了优化?

标签: flash apache-flex actionscript-3 applicationdomain


【解决方案1】:

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

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

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

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 位于同一位置,或其父文件夹之一。 Here's a non-restrictive cross-domain file according to documentation from Adobe:

<?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 点#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 
{
    ...
}

【讨论】:

  • 我的错,应该澄清这是一个 AIR 应用程序,从本地文件系统加载,因此策略文件无关紧要。我认为第二种方法应该可行,我想到了这个,但它太乱了。我至少需要在两个 SWF 之间共享 3 个不同的类,并且在太多的方法中进行了大量的通信,每次从子类中提取定义似乎是一种非常不优雅和繁琐的方法。我想要的是一种让孩子与父母的定义兼容的方式。有什么想法吗?
  • 如果您参考文档的链接以了解 ApplicationDomain 的不同选项,它会说:“如果父级希望使用子级的类,则必须调用 ApplicationDomain.getDefinition() 来检索它们”,并且“如果孩子试图定义一个与父类已经定义的类同名的类,则使用父类并忽略子类。”和“任何一方看到对方类的唯一方法是调用ApplicationDomain.getDefinition() 方法”。所以似乎 getDefinition() 是覆盖子定义的类的唯一方法。
  • 并且使用父母的定义而忽略孩子的定义正是我想要的。正如我在上面自己的回答中提到的那样,我发现了这个问题,它只有在父母和孩子在同一个安全沙箱中时才有效。
【解决方案2】:

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

【讨论】:

【解决方案3】:

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

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

包 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('来自共享类的你好'); } } }

【讨论】:

  • 事实上这正是我正在做的事情。但是这一行 child = event.currentTarget.content as Child;不起作用,因为由于某种原因,Flash 播放器将“子”类的定义视为父子类的不同,这很奇怪,因为根据 Adob​​e 的文档不应该发生冲突,孩子的定义被丢弃并且父母的被收养。还有什么想法吗?
  • 如果你跟踪 event.currentTarget.content 的输出是什么?
【解决方案4】:

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

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 中的类使用不同的名称或名称空间。

【讨论】:

    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 2015-05-11
    • 2019-12-22
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-03-17
    相关资源
    最近更新 更多