10 Replies Latest reply on Apr 23, 2008 5:21 PM by jpsoul

    Type Casting Loaded Swf

    jpsoul Level 1
      I'm having trouble type casting an MXML created swf as in I can't seem to get it to work.

      Here is what I'm doing:
      1. Created a LoaderTest.swf that loads AppToLoad.swf
      2. Made AppToLoad implement ISomeInterface
      3. Once AppToLoad.swf is loaded in LoaderTest.swf, attempt to type
      cast it as ISomeInterface

      Code (all code is in the same root package):

      <!-- Begin ISomeInterface -->

      package
      {
      public interface ISomeInterface
      {
      function doSomething():void;
      }

      }

      <!-- End ISomeInterface -->

      <!-- Begin AppToLoad -->

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"
      layout="absolute" implements="ISomeInterface">
      <mx:Script>
      <![CDATA[
      private var myInterface:ISomeInterface;

      public function doSomething():void
      {
      trace("doSomething");
      }
      ]]>
      </mx:Script>
      </mx:Application>

      <!-- End AppToLoad -->

      <!-- Begin LoaderTest -->

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx=" http://www.adobe.com/2006/mxml"
      layout="absolute" applicationComplete="start()">
      <mx:Script>
      <![CDATA[
      import mx.managers.SystemManager;
      private var ldr:Loader;
      private function start():void
      {
      ldr = new Loader();
      var ldrContext:LoaderContext = new LoaderContext(false,
      ApplicationDomain.currentDomain);
      ldr.contentLoaderInfo.addEventListener(Event.INIT, handleLoaded);
      ldr.load(new URLRequest("AppToLoad.swf"), ldrContext);
      }
      private function handleLoaded(e:Event):void
      {
      trace("handleLoaded");
      var content:Object = LoaderInfo(e.target).content;
      trace("content = "+content);
      var typedContent:ISomeInterface = content as ISomeInterface;
      trace("typedContent = "+typedContent);
      var typedApplication:ISomeInterface = (content as
      SystemManager).application as ISomeInterface;
      trace("typedApplication = "+typedApplication);
      }
      ]]>
      </mx:Script>

      </mx:Application>

      <!-- End LoaderTest -->

      Output from running LoaderTest:

      [SWF] C:\EDGE\testFolder\bin-debug\LoaderTest.swf - 555,437 bytes
      after decompression
      [SWF] C:\EDGE\testFolder\bin-debug\AppToLoad.swf - 554,844 bytes after
      decompression
      handleLoaded
      content = [object _AppToLoad_mx_managers_SystemManager]
      typedContent = null
      typedApplication = null

      Any idea what I'm doing wrong?

      -JP
        • 1. Re: Type Casting Loaded Swf
          slaingod Level 1
          I'd be interested in seeing the solution as well, but a quick workaround is to cast it to the unbind operator.
          This is how I've always done it... Maybe you can get it to work with implements:

          <?xml version="1.0" encoding="utf-8"?>
          <mx:Canvas xmlns:mx=" http://www.adobe.com/2006/mxml" >

          <mx:Script>
          <![CDATA[

          import mx.events.FlexEvent;
          import mx.managers.SystemManager;
          import mx.core.Application;

          // * gets rid of type checking so we can leave strict enabled
          [Bindable]public var _appLoaded:*;

          private var load_finish_playlist:int = 0;
          private var load_finish_name:String = "";

          private function onCurrentApplicationComplete(oEvent:Event):void
          {
          _appLoaded = Application(oEvent.target.application);
          if(load_finish_playlist > 0) {
          setPlaylist(load_finish_playlist);
          }
          if(load_finish_name != "") {
          setPlayerName(load_finish_name);
          }
          }

          private function onCompleteAppLoader(oEvent:Event):void
          {
          var smAppLoaded:SystemManager = SystemManager(oEvent.target.content); //get a ref to the loaded app
          //listen for the application.complete event
          smAppLoaded.addEventListener(FlexEvent.APPLICATION_COMPLETE, onCurrentApplicationComplete);
          }

          public function setPlaylist(id:int):void {
          if(_appLoaded) {
          _appLoaded.change_playlist(id);
          } else {
          load_finish_playlist = id;
          }
          }

          public function setPlayerName(name:String):void {
          if(_appLoaded) {
          _appLoaded.set_name(name);
          } else {
          load_finish_name = name;
          }
          }

          public function stopPlayback():void {
          _appLoaded.stop_playback();
          }

          public function startPlayback():void {
          _appLoaded.start_playback();
          }

          ]]>
          </mx:Script>

          <!-- <mx:SWFLoader id="player" x="0" y="0" source=" http://...../flash/mixplayer3.swf" complete="onCompleteAppLoader(event);" trustContent="true"/>
          --> <mx:SWFLoader id="player" x="0" y="0" source="@Embed('../assets/Player.swf')" complete="onCompleteAppLoader(event);" trustContent="true"/>

          </mx:Canvas>
          • 2. Re: Type Casting Loaded Swf
            jpsoul Level 1
            yeah, what i really want is to be able to call the api of my loaded swf with strict compiling. i'm not sure if your workaround satisfies that. interesting idea though to add an event handler for the application complete of the loaded swf. i haven't been able to get that to work as your example suggests (since I don't have your assets I can't compile your example).

            there has to be a way to do this.
            • 3. Re: Type Casting Loaded Swf
              jpsoul Level 1
              Okay, I think I figured it out.

              In order to type cast a loaded mxml compiled swf to an interface that it implements:

              #1. You need to wait for the applicationComplete event to occur before type casting.

              #2. Use the SWFLoader instead of a Loader as the Loader (or more precisely, the LoaderInfo object of the Loader) will not dispatch applicationComplete events.

              This worked for me.
              • 4. Re: Type Casting Loaded Swf
                jpsoul Level 1
                Just to be clear, the operation to type cast was:
                var app:ISomeInterface = SystemManager(swfLoader.content).application as ISomeInterface;

                where as if the swf was created with ASOnly, by extending Sprite instead of Application you would need to do this:
                var app:ISomeInterface = swfLoader.content as ISomeInterface;
                • 5. Re: Type Casting Loaded Swf
                  levancho Level 3
                  you can also just change this
                  ldr.contentLoaderInfo.addEventListener(Event.INIT, handleLoaded);
                  to this
                  ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoaded);
                  and should work as well

                  • 6. Re: Type Casting Loaded Swf
                    jpsoul Level 1
                    Hi Levancho,

                    Using the Complete event for the contentLoaderInfo prop didn't work for me. Do you have an example of this working? I could only get the results I wanted from the swfloader and the app complete event.
                    • 7. Re: Type Casting Loaded Swf
                      jpsoul Level 1
                      I'm attaching my code that I used for testing this. I tried loading an MXML created swf using both the complete event of the Loader.contentLoaderInfo and I used the Application Complete event of the SWFLoader. I also loaded a AS Only created clip with the swf loader. This should demonstrate what I've been talking about in the thread.
                      • 8. Re: Type Casting Loaded Swf
                        jpsoul Level 1
                        Damn, this code worked for me at home but now I'm trying it on my work machine and its not working anymore. The only swf that I can type cast to an interface is the ASOnly swf.

                        This is very frustrating. Anyone have any ideas why this is happening?
                        • 9. Re: Type Casting Loaded Swf
                          levancho Level 3
                          most like you need to use flex version of loader which is SWFLoader and it will work for sure.
                          • 10. Re: Type Casting Loaded Swf
                            jpsoul Level 1
                            Okay, I got it to work on my work machine. slaingod had the right idea...Thanks! After the swf is loaded, I needed to wait for the FlexEvent.APPLICATION_COMPLETE to happen. When that is done I can get access to the SystemManager(ldr.content).application and cast it. My home computer is much faster than my work machine which I think is why it worked at home.

                            Now to make a custom class that hides all that after a complete event and exposes the content as an object, either the extension of application for MXML or Sprite for ASOnly, which I can cast.