2011-08-13 14 views
2

私は、クラスのオブジェクトを 'MyBigAwesomeClass'という子から親に渡したいという状況があります。クラス定義を親と子の両方にインポートします。親子SWF間でクラスを共有

親の場所からの相対的な位置から子SWFをロードすると、すべてが正常ですが、完全な絶対パスを使用してロードすると、 'BigAwesomeClass'の定義が親クラスと子クラスの異なるオブジェクトであり、 'BigAwesomeClass'型のオブジェクトを親クラスの同じオブジェクトに割り当てることを許可しません。

は、私は完全に困惑していますが、このコード

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

絶対に無駄に使用を含む、に、ApplicationDomain上で、私の頭を打ちました。 これを修正するにはどうすればよいですか?アドビのドキュメント(Loader#securityDomain)によると

事前

+0

子SWFを作成するときは、親SWF用に最適化していますか? –

答えて

1

それはサンドボックスの問題です。インストーラの一部ではないファイルは別のセキュリティサンドボックスに配置され、異なるサンドボックスに格納されるため、親にインポートされたときに子はApplicationDomainに親の定義を継承せず、互換性のない2つの別個の定義が存在します。残念ながら、これを解決する直接的な方法はないようです。アドビはSandBoxBridge経由でサンドボックス間の通信を許可していますが、オブジェクトタイプを使用する必要があります。これはオブジェクト全体の目的に反するものです。私が知る限り、2つの異なるサンドボックスのクラスは、まったく同じでも互換性がありません。私はオブジェクトの厳密なタイピングのない苦しい世界をその背後にあると思います。

+0

同様の問題を持つ人を支援するためのリンク。 http://www.senocular.com/flash/tutorials/contentdomains/?page=2 ApplicationDomainsのすばらしい記事です。特に、次のセクションを参照してください。同じ定義の衝突、アプリケーションドメインの継承) Adob​​eのAIRのサンドボックスの制限と、それを回避する方法については、http://livedocs.adobe.com/flex/3/html/helpを参照してください。 html?content = security_5.html#1092959 –

1

のおかげでは:

読み込みロードが成功するためには、ロードされたSWFファイルのサーバー は、ロードのドメインを信頼するポリシーファイルを持っている必要がありますSWFファイル。

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); 

添付のクロスをdomain.xmlをする必要がありますトリックは例えば、swfファイルをロードするときにLoaderContextを作成するときに最初のパラメータとしてtrueを渡すことによって、クロスドメインファイルをチェックするために、Loaderを言っている

子SWFと同じ場所に配置することも、親フォルダの1つに配置することもできます。 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を参照)。子クラスは、そのオブジェクトがインタフェースに準拠している限り、各オブジェクトの独自のバージョンを安全にインスタンス化できます。例えば:私は、問題はおそらく親&子のアプリケーションドメインに関係していることをあなたに同意、しかしになり

public class MyBigAwesomeClass implements IMyBigAwesomeInterface 
{ 
    ... 
} 
+0

私は悪いですが、これはローカルファイルシステムからロードするAIRアプリケーションであることを明確にしているはずです。したがって、ポリシーファイルは関係ありません。 私が思う第二のアプローチはうまくいくはずですが、私はこれを考えましたが、あまりにも面倒です。私は2つのSWFの間で共有する必要のある少なくとも3つの異なるクラスを持っており、あまりにも多くの方法で多くのコミュニケーションが行われており、毎回子クラスから定義を抽出するのは非常にエレガントで厄介なアプローチです。私が望むのは、子供が親の定義と適合するための方法です。何か案は ? –

+0

ApplicationDomainのさまざまなオプションのドキュメントへのリンクを参照すると、「親が子クラスを使用する場合は、ApplicationDomain.getDefinition()を呼び出して取得する必要があります」、および「子が親クラスですでに定義されているクラスと同じ名前のクラス、親クラスが使用され、子クラスは無視されます。 "、および"両サイドで他のクラスを見る唯一の方法は、ApplicationDomain.getDefinition()メソッドを呼び出すことです"したがって、getDefinition()は、子で定義されたクラスをオーバーライドする唯一の方法です。 –

+0

そして、親の定義を使用し、子供のそれを無視することは、まさに私が望んでいたものです。問題は、親と子が同じセキュリティサンドボックス内にある場合にのみ動作することを、私自身の答えで言及したとおり、発見しました。 –

0

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

はMyBigAwesomeClassの定義は、次のようになりますより正確に答えるためには、親と子の間で共有したいクラスの使用例をいくつか使用するとよいでしょう。

理論的には、クラスが子供のために定義されていれば、問題は回避できると思われます...ここでは、私の意見では子供を読み込む場所であれば動作するはずの非常に基本的な例です。

 
package com.example.test 
{ 
    public class Parent extends Sprite 
    { 
     private var child:Child; 
     private var shared:SharedClass = new SharedClass(); 

     public function Parent() 
     { 
     loadChild(); 
     } 

     private function loadChild():void 
     { 
     // load process 
     } 

     private function loadComplete(event:Event):void 
     { 
      child = event.currentTarget.content as Child; 

      if(child != null) 
      shared = child.shared; 
      // remove event etc... 
     } 
    } 
} 

package com.example.test 
{ 
    public class Child extends Sprite 
    { 
     // I use a public var here , but you can use a getter... 
     public var shared:SharedClass; 

     public function Child() 
     { 
      shared = new SharedClass(); 
     } 
    } 
} 

package com.example.test 
{ 
    public class SharedClass 
    { 
     public function SharedClass() 
     { 
      trace('Hello from Shared Class'); 
     } 
    } 
} 
+0

これは実際に私がやっていることです。しかし、この行 子= event.currentTarget。子供としてのコンテンツ; 何らかの理由でFlash Playerが「Child」クラスの定義を「親」と「子供」の違いとして扱っています。これは奇妙なことです。なぜなら、Adobeの文書によれば、競合が発生してはならないからです。捨てられ、親が採用される。これ以上のアイデアは? –

+0

event.currentTarget.contentをトレースすると、何が出力されますか? – PatrickS

0

1つのオプションは、使用してクラスのインスタンスを返すために、子クラスのメソッドを実装して使用することで、それ自身のApplicationDomain、例えば:

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に通知します。

Flashは静的型定義を使用します。つまり、クラスが定義されると決して変更されません。つまり、クラス定義を別のクラス定義に上書きすることは決してありません。したがって、同じ名前のクラスが2つある場合は、矛盾する名前を解決するためにはgetDefinitionを使用する必要があります。複雑さが増すのを避けたい場合は、親SWFと子SWFのクラスに異なる名前または名前空間を使用できます。

関連する問題