2011-08-16 10 views
1

私はprevious questionの例に従い、ローダーを使用して外部swfをロードしています。ローダーイベントハンドラー内でloader.contentを私のキャストしようとしています。AS3:MovieClipを拡張するカスタムクラスとしてswfをロードする - ヌルオブジェクト参照を取得する

TypeError: Error #1009: Cannot access a property or method of a null object reference.

だけswfファイルの場所が正しかったとswfファイルが実際にロードされていたことを確認し、テストするために、私は変更:MovieClip

私はこのエラーが発生した公開する場合を拡張するカスタムクラスPanelReferenceClipコンテンツのタイプはas MovieClipになりました。うまくいきました。

編集:これらのswfsはローカルに保存されており、インターネット、複数のネットワークまたはサーバーを経由して取得されないことを追加したいとも考えました。

私は私のクラスで風変わりな何かをした場合ので、私はここに私のカスタムクラスにPanelReferenceClip

package com.components 
{ 
    import com.UI.DevicePanel; 
    import flash.display.MovieClip; 

    /** 
    * ... 
    * 
    * used to store the loaded swf inside the panel 
    * 
    * *parentPanel is set so that it is able to access it's parent Panel when needing 
    * to set parameters. 
    */ 

    public class PanelReferenceClip extends MovieClip 
    { 
     private var _parentPanel:DevicePanel; 
     private var _bg_mc:MovieClip; 
     private var _oldY:Number = 0; 
     private var _oldX:Number = 0; 
     private var _IsDragging:Boolean = false; 

     public function PanelReferenceClip() { 
      super(); 
     } 

     /*-------------------------------------------------------------------------- 
     * GETTERS AND SETTERS 
     * -----------------------------------------------------------------------*/ 

     public function set parentPanel(p:DevicePanel):void { 
      _parentPanel = p; 
     } 

     public function get parentPanel():DevicePanel { 
      return _parentPanel; 
     } 

     public function get bg_mc():MovieClip { 
      try { 
       return getChildByName("bg_mc") as MovieClip; 
      } catch (e:Error) { 
       trace("could not find bg_mc in " + _parentPanel.DeviceName + " panel"); 
      } 

      return null; 
     } 

     public function set oldY(n:Number):void { 
      _oldY = n; 
     } 

     public function get oldY():Number { 
      return _oldY; 
     } 

     public function set oldX(n:Number):void { 
      _oldX = n; 
     } 

     public function get oldX():Number { 
      return _oldX; 
     } 

     public function set IsDragging(b:Boolean):void { 
      _IsDragging = b; 
     } 

     public function get IsDragging():Boolean { 
      return _IsDragging; 
     } 
    } 

} 

をソースを提供していますかわからないがSWFをロードした後にしようとしている別のクラスの一部であり、それらをタイプPanelReferenceClipのクラスprop _referenceとして割り当てます。私はswfを取得することができるので、swfを取得することができます。swfをインポートすると、インポートされたswfのインスタンス名を設定しないためです。だから私はカスタムクラスを割り当てて、MovieClipを拡張するので、いくつかのカスタムプロパティを保存することができます。

 private function handleLoad(e:Event):void 
     { 
      e.target.removeEventListener(Event.COMPLETE, handleLoad, false); 
      // keep reference to the content 
      _reference = e.target.content as PanelReferenceClip; 
        // ** BREAKS ON THE NEXT LINE **/ 
      trace(_reference.numChildren); 

      // add loader to the display list so we can see the external SWF. 
      addChild(e.target.loader); 

      // signal the sim engine that the swf has loaded 
      // and to go ahead and wire up the components 
      dispatchEvent(new DataEvent(DataEvent.COMPLETE)); 

      initPanel(); 
     } 

swfを読み込むためのメソッドです。私はそれを試してアプリケーションのコンテキスト部分を追加しましたが、私はまだどこにも取得していません。ローダSWFがあり、どこで、それは外部のSWFをロードしないから、どこそれは非常に重要であるとして提供

public function loadSWF(theSWF:String):void 
    { 
     var url:String = theSWF; 
     var urlReq:URLRequest = new URLRequest(url); 
     _urlError = url; 
     _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoad); 
     _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 
     var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); 
     _loader.load(urlReq,context); 
     _loader.mouseEnabled = false; 
    } 

答えて

1

これは、t ypecast。 someVariable as OtherClassを実行する際にエラーが発生する代わりに、変数はnullになります。 (例示さ)

私はPanelReferenceClipのプロパティの一つとして、元のムービークリップへの参照を格納し、ちょうどあなたが.numChildren

//MovieClips are subclasses of Sprites... this conversion works 
var originalMC:MovieClip = new MovieClip(); 
var sprite:Sprite = originalMC as Sprite; 
trace("sprite: " + sprite); //defined 

//Sprites are not subclasses of MovieClips... this conversion wont work 
var originalSprite:Sprite = new Sprite(); 
var mc:MovieClip = originalSprite as MovieClip; 
trace("mc: " + mc); //null 

//MovieClips are not subclasses of PanelReferenceClips (quite the opposite) 
//this conversion wont work, just as the one before 
var panelRef:PanelReferenceClip = originalMC as PanelReferenceClip; 
trace("panelRef: " + panelRef); //null 
+0

そうですね問題。あなたのソリューションを試してみよう。 –

1

事実が、決定的ではありません。

私の推測:ロードされたコンテンツは、別のApplicationDomainにあります。 LoaderContext.applicationDomainおよびLoader.load()メソッドの第2パラメータを参照してください。

機械の詳細。明らかに、PanelReferenceClipクラスを2つの異なるSWFファイルにコンパイルします。コードを含む外部SWFファイルをロードすると、VMは、入力したローダコンテキストに応じて、ロードされた宣言をローダSWFのものと混在させるかどうかを決定します。指定したコンテキストで混合が可能な場合、受信SWFは親SWFと同じ修飾名を持つ同じ宣言を使用します。そうでない場合、完全修飾名が同一であっても、初期化されるクラスは異なります。後者の場合、読み込んだコンテンツを好きなものにキャストすることはできません。出力は必ずしもクラスが同じであること、を意味するものではありませんので、同じであっても

trace(getQualifiedClassName(e.target.content)); // This is the incoming declaration 
trace(getQualifiedClassName(PanelReferenceClip)); // This is the parent declaration 

handleLoad()方法で次のテストを試してみてください。ある種類のデバッガを使用している場合は、次のテスト行のメモリアドレスを調べることができます。

var incomingClass:Class = e.target.content["constructor"]; 
var residentClass:Class = PanelReferenceClip; 
trace(incomingClass == residentClass); // toggle breakpoint here and compare memory addresses 
+0

のようなものにアクセスする必要があるときに私は投稿するつもりです、その参照を使用しますメソッドは、あなたのためのローダーを持っています。 –

1

@ nox-noctisに記載されているように、問題はapplicationDomainに起因する可能性があります。私はsimilar question hereと答えました。

問題の根底には、PanelReferenceClipの2つの異なるクラスが実際に定義されているということがあります。同じ名前を持ち、同じコードを含んでいても、Flashはそれらを2つの異なるオブジェクトと見なします。

クラスに2つの異なる名前を付けると、クラスがどのようにFlashに見えるかがより明確に伝わります。本質的には、あなたは例えば、異なるタイプの1つのオブジェクト型をキャストするには、Flashを言っている:

var foo:Foo = new Foo(); 
var bar:Bar = foo as Bar(); // where Bar does not inherit Foo 

働くだろうどのようなパネルは、ムービークリップを拡張しないためしかし、MovieClipように、パネルをケースです。これにより、ディスプレイリストに追加できるようになりますが、パネルの実装にAPIは提供されません。

解決策の1つは、クラスのインターフェイスを指定することです。これは、コードが異なっていても、2つのクラスを同じ方法で使用できることをFlashに伝えます。これには、クラス全体ではなく親SWFにインターフェイスをコンパイルするだけで、親のファイルサイズが小さくて済むという利点もあります。パネルの

インタフェースは次のようになります。

public interface IPanelReference 
{ 
    function set parentPanel(p:IDevicePanel):void; 
    function get parentPanel():IDevicePanel; 
    function get bg_mc():MovieClip; 
    function set oldY(n:Number):void; 
    function get oldY():Number; 
    function set oldX(n:Number):void; 
    function get oldX():Number; 
    function set IsDragging(b:Boolean):void; 
    function get IsDragging():Boolean; 
} 

をこのようなパネルへのインタフェースを適用します。

public class PanelReferenceClip extends MovieClip implements IPanelReference 
{ 
    ... 
} 

親はその後、インタフェースによってロードされたクラスを参照し、既知のでしょう先祖:

private function handleLoad(e:Event):void 
{ 
    ... 
    _reference = e.target.content as IPanelReference; 
    trace((_reference as DisplayObjectContainer).numChildren); 
    trace(_reference.oldX); 
    addChild(_reference as DisplayObject); 
    .... 
} 
+0

私はこのクラスを作成しました。私がロードしているswfsは、アートワーク関連のものとカスタムコントロールのようなカスタムの 'MovieClip'クラスです。私が 'MovieClip'としてそれを持ってきて' _reference'に代入すると、 'PanelReferenceClip'が' MovieClip'を拡張しても 'MovieClip'を' PanelReferenceClip'型にキャストすることができないというエラーが発生します –

関連する問題