Loaderの設定に関する注意点 - LoaderContext
どうもtaroです.
少々マニアックですが、flash.display.Loader.loadの第2引数にLoaderContextを設定することが出来るのですが、そのことについてのまとめと嵌らないための注意点です.
ランタインム・クラスを利用しようとするとき、これらの設定が必要となることがあります。
var context:LoaderContext = new LoaderContext; context.checkPolicyFile = true; context.applicationDomain = ApplicationDomain.currentDomain; context.securityDomain = SecurityDomain.currentDomain; var ldr:Loader = new Loader; ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, onSWFLoaded); ldr.load(new URLRequest(SWF_PATH), context); function onSWFLoaded(e:Event):void { var c:Class = ldr.contentLoaderInfo.applicationDomain.getDefinition("RuntimeClass") as Class; var instance:* = new c; }
checkPolicyFile
2行目で設定している項目。
これは、異なるドメインにある画像などを読みに行くときに有効な設定です。trueにセットすると、読込先のドメインにポリシー・ファイルをデフォルトの位置"/crossdomain.xml"に読み込みに行きます。
もし/crossdomain.xmlが存在しなくてもエラーとはなりませんが、セキュリティー・サウンド・ボックスを侵害するような操作をすると、エラーが起きます。
applicationDomain
3行目で設定している項目。
これは色々な設定が可能ですが、幾つかのパターンについてご説明します。
applicationDomain = ApplicationDomain.currentDomain
これは、読みこみの親と子のApplicationDomainを同じであるように設定します。ロードが完了すると、親から子、子から親とお互いにお互いで定義されているクラスを参照することが可能です。ただし、読みこみ先のSWFが異なるドメインにある場合、securityDomainの項目もご確認下さい。
もし親のSWF内に存在するクラスと同名のクラスが子供のSWFに存在する場合、親のクラスが優先され、子供のクラスは無視されます。複数の同名のクラスを読み込む場合は、この設定ではなく、他の設定にする必要があります。
applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain)
これについて、若干不明点があります。こちらは、リファレンスよりの抜粋なのですが、
The default. You can explicitly represent this choice with the syntax new ApplicationDomain(ApplicationDomain.currentDomain). This allows the loaded SWF file to use the parent's classes directly, for example by writing new MyClassDefinedInParent(). The parent, however, cannot use this syntax; if the parent wishes to use the child's classes, it must call ApplicationDomain.getDefinition() to retrieve them. The advantage of this choice is that, if the child defines a class with the same name as a class already defined by the parent, no error results; the child simply inherits the parent's definition of that class, and the child's conflicting definition goes unused unless either child or parent calls the ApplicationDomain.getDefinition() method to retrieve it.
ロードされたSWFからnew MyClassDefinedInParent()と直接出来るとありますが、コンパイル時にMyClassDefinedInParentの定義がないと成立しないし、何のことを言っているのかがちょっと分かりません。また子と親に同名の定義があるとき、親の定義が優先されるとありますが、こちらもちょっと確認できませんでした。結局、この設定は、
applicationDomain = new ApplicationDomain(null)
と同じ働きのような気がします。さて、ここは不明な所でありますが、こちらの設定の良い所は、同じ名前のクラスの定義を含む複数のswfファイルを読み込む場合、これらの設定にすると良いです。
以下がサンプルになります。このサンプルでは Runtime_Sample_CustomDataStructure という名前をドキュメントクラスとする二つのswfをロードして、それぞれ別々に定義されているメソッドを実行しています。
INFINITY TANK BATTLEでもタンクのクラスは全て、Tankという同じクラスなので、同じ仕組みを使っています。
securityDomain
こちらは、ランタイム・クラスとして読み込むswfが別ドメインにある時に、設定する必要があります。
別ドメインにある場合、同じクラスでもそれぞれ別のクラスとして認識されてしまうため、ランタイム・クラスのメソッドと読みこみ側で同じ型のクラスを共有することが出来なくなってしまいます。
その為、名前が同じだけれど、関連性のないクラスとして二つが扱われ、強制型変換が起きてしまいます。
もし、別ドメインにランタイムのクラスを読み込んでいて、強制型変換がどうのというようなエラーが起きるとき、もう一度こちらの設定を確認することをオススメします。