상세 컨텐츠

본문 제목

로드한 SWF 내부에 작성된 ActionScript 3.0 클래스 이름 찾기, 라이브러리에 swc 클래스 찾기 로드 관련, 외부swf 안에 클래스로드 관련

ADOBE/ ActionScript

by AlrepondTech 2020. 9. 23. 02:20

본문

반응형

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

출처: http://blog.jidolstar.com/474

ActionScript 3.0의 ApplicationDomain은 로드한 SWF파일 내부에 정의된 Class를 참조하는데 유용하게 쓰인다.

 

ApplicationDomain은 현재 hasDefinition(name:String):Boolean 과 getDefinition(name:String):Object 등 2개의 public 메소드를 지원한다. 이 메소드를 이용하여 ApplicationDomain내 정의된 클래스 정의 유무를 알 수 있고 그에 대한 참조를 얻을 수 있다. 다음은 사용 예이다.

var myInstance:DisplayObject = new
(ApplicationDomain.currentDomain.getDefinition("com.flassari.MyClass"));

 

위 코드의 경우 현재 애플리케이션의 ApplicationDomain상에 정의된 com.flassari.MyClass 클래스의 정의를 읽어와 DisplayObject 객체를 만드는 것이다. 사용하기 매우 쉽다. 그러나 클래스의 이름을 알고 있다는 전재하에 쓰일 수 있는 방법이다. 그럼 ApplicationDomain 내에 정의된 이름을 알지 못하는 클래스들의 이름을 목록을 알고 싶을 때는 어떻게 해야할까? 불행히도 ApplicationDomain 클래스는 이것을 지원해주고 있지 않다. ApplicationDomain.getAllDefinitions():Array 와 같은 메소드가 지원된다면 좋을 텐데 말이다.

 

해결방법이 있다. 바로 여기에서 소개하는 SwfClassExplorer 클래스를 이용하면 된다. 사용방법은 매우 단순하다. 하나의 static 메소드인 getClasses(bytes:ByteArray):Array 를 이용하면 된다. 아래 코드는 간단한 사용예제이다.

public function init():void {
    // Load the swf
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
    urlLoader.addEventListener(Event.COMPLETE, onSwfLoaded);
    urlLoader.load(new URLRequest("pathToSwf"));
}


private function onSwfLoaded(e:Event):void {
    // Get the bytes from the swf
    var bytes:ByteArray = ByteArray(URLLoader(e.currentTarget).data);
    // And feed it to the SwfClassExplorer
    var traits:Array = SwfClassExplorer.getClasses(bytes);
    for each (var trait:Traits in traits) {
        trace(trait.toString()); // The full class name
    }
}

 

이는 매우 유용함을 알 수 있다. SWF를 Loader가 아닌 URLLoader로 로드했음을 볼 수 있다. 그리고 실제 DisplayObject 객체를 생성하기 위해 다음과 같이 코딩하면 되겠다.

private var _loader:Loader;


public function init():void {
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
    urlLoader.addEventListener(Event.COMPLETE, onSwfLoaded);
    urlLoader.load(new URLRequest("pathToSwf"));
}


private function onSwfLoaded(e:Event):void {
    var bytes:ByteArray = ByteArray(URLLoader(e.currentTarget).data);
    var traits:Array = SwfClassExplorer.getClasses(bytes);
    for each (var trait:Traits in traits) {
        trace(trait.toString()); // The full class name
    }


    selectedClassName = traits[0];
    _loader = new Loader();
    var loaderContext:LoaderContext = new LoaderContext();
    _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaderInit);
    _loader.loadBytes( bytes, loaderContext );
}


private function onLoaderInit(event:Event){
    var obj:Object;
    try {
        obj = new (_loader.contentLoaderInfo.applicationDomain.getDefinition(selectedClassName ));
    } catch (e:Error) {
        trace( "Can't instantiate class:\n" + e.toString() );
    }
    if (obj != null && obj is DisplayObject) {
        addChild( DisplayObject(obj) );
    }
}

결국 Binay형태로 받아온 SWF를 Loader클래스의 loadBytes()메소드를 이용해 비동기적으로 로드처리한 뒤에 Loader.contentLoaderInfo.applicationDomain의 getDefinition() 메소드를 이용해 객체를 생성하는 방식이다.

아쉬운 점은 여기서 loadBytes()를 이용한 비동기적 처리가 아닌 동기적 처리를 통해 클래스 참조를 얻어낼 수 있다면 더욱 좋을 것 같다.  사실 이 부분을 찾다가 이 예제를 찾아내게 된건데 매우 유용해서 포스팅 한 것이다.

세부적인 예제 및 소스는 아래 출처를 참고한다.

 

출처

Swf Class Explorer for AS3

소스

위 출처에서 소스를 다운받을 수 없으면 아래 링크로 다운받는다.

as3cne (1).zip
0.80MB

 

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://www.flashdevelop.org/community/viewtopic.php?p=27575

Previous topic | Next topic 

problem with getDefinitionByName 

AuthorMessage

 problem with getDefinitionByName
Hi, i'm getting a [Fault] exception, information=ReferenceError: Error #1065: No se ha definido la variable Chest_s. wich means that "Chest_s" is a undefined variable.

this is the code...

Code:
       var Aux:Class = getDefinitionByName( "Chest_s" ) as Class;


Chest_s is a class inside my swc library and it extends of "Classes.Items.Chest"

the thing is if I do this it works fine !

Code:
       var tempChest:Chest_s;
       var Aux:Class = getDefinitionByName( "Chest_s" ) as Class;



 
 
 Re: problem with getDefinitionByName
The problem is that by default the compiler only includes a class from a .swc if the class is actually referenced in code, as in your second example. In the first code the Chest_s class is unknown until runtime, when it's too late. 

The solution is to add your swc to the list in the Project Properties -> Compiler Options -> SWC Include Libraries list. That way all classes in the swc are compiled in regardless.



 
 
 Re: problem with getDefinitionByName
Correct, or you can add references to each symbols in your code like you did - but these references could be put outside your class after the package {} declaration.


 
 
 Re: problem with getDefinitionByName
yes ...
the most simple thing is to put them into an Array-literal ... [MyClass1,MyClass2,MyClass3]

personally i don't use getDefinitionByName, since i think it is not flexible enough ...
usually i register classes to some controller, where i then can make a lookup, since i feel it gives me more control, and avoids redundancy ... and it makes sure all classes i want are referenced ... here's an example from a smaller project ...


Code:
class ClassResolver {
   private static var _classes:Object = { };
   /**
    * registers a class for a given id and returns success
    * @param   theClass the class to be registered
    * @param   id the id under which the class is to be registered
    * @param   overwrite if true, the potentially registered class for the id is overwritten
    * @return
    */
   public static function registerClass(theClass:Class, id:String, overwrite:Boolean = false):Boolean {
      var ret:Boolean = overwrite || !_classes.hasOwnProperty(id);
      if (ret) _classes[id] = theClass;
      return ret;
   }
   /**
    * registers multiple classes and returns an Array of ids, where registration failed
    * throws an Error, if no class is found where expected
    * @param   classes an Object mapping ids to classes
    * @param   overwrite see ClassResolver.registerClass
    * @return
    */
   public static function registerClasses(classes:Object, overwrite:Boolean = false):Array {
      var ret:Array = [];
      for (var id:String in classes) {
         if (classes[id] is Class) {
            if (!registerClass(classes[id], id, overwrite)) ret.push(id);
         }
         else throw new Error("parameter "+classes[id]+" for id \""+id+"\" is not a class");
      }
      return ret;
   }
   /**
    * lookups the class registered for a given id
    * @param   id
    * @param   panicIfUndefined if true, lookup to a non existent class will throw an Error
    * @return
    */
   public static function getClass(id:String, panicIfUndefined:Boolean = true):Class {
      if (panicIfUndefined && !_classes.hasOwnProperty(id)) throw new Error("no class registered for id \""+id+"\"");
      return _classes[id];
   }
   /**
    * tells whether a class exists for the given id
    * @param   id
    * @return
    */
   public static function classExists(id:String):Boolean {
      return _classes.hasOwnProperty(id);
   }
}



and then lookup classes through the controller ... that way, if you need to exchange a class, you only have to do it in one place ... and you can influence the behaviour ... for example return a default class if none is defined, such as Object ...

but then again it's all a matter of taste ... 



 
 
 Re: problem with getDefinitionByName
thanks everyone !


 
 
 Re: problem with getDefinitionByName
Hi!

I donno if someone can help me, but I've similar problem, the difference is that my Class isn't in SWC file, it's under the package pages in src folder.

I've searched around but it seems everyone have the same problem but with SWC file.


Code:
var pageToBeOpen:Class = getDefinitionByName('pages.Home') as Class;


I've tried everything I could think of, but keeps telling me 


Quote:
[Fault] exception, information=ReferenceError: Error #1065: Variable Home is not defined.


Any help would be very much appreciated and smooths my transition from FB to FD 



 
 
 Re: problem with getDefinitionByName
Are you trying to reference a class that's compiled in the same SWF, or is this a class that is being loaded from another SWF?

If so, pay attention to the Application Domain of the loaded SWF. Unless you load the new SWF inside the same Application Domain as the parent SWF, the classes exist in different sandboxes.



 
 
 Re: problem with getDefinitionByName
Thx for the help, but I came to the conclusion that Class Home isn't being referenced anywhere in my code...  

Now I have to find a solution similar to what back2dos posted

Sorry 



 
 
 Re: problem with getDefinitionByName
Hello all, happy new year  

Quick question about applicationDomain.

I have an external .swf which I load in my main swf and load Classes from, like this:


Code:
loader = new Loader();
request = new URLRequest("mySwf.swf");
context.applicationDomain = ApplicationDomain.currentDomain;

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadClasses);
loader.load(request, context);

...

private function loadClasses(e:Event):void 
{
      newClass = getDefinitionByName("className") as Class;
}




It worked fine while I was working in Flash IDE. Last week I changed my compilation method only inside FlashDevelop using Flex SDK's compiler. While I was testing with popup, everything still was fine. When I changed Test Movie option to external player (debug Flash Player) so I could use the FlexDBG plugin, I got Variable <className> is not defined errors for all the .swf classes.

Do I have to use another option for applicationDomain? or is something wrong with my setup when using the external player option?

thanks 



 
 
 Re: problem with getDefinitionByName
If you believe that the problem is in sandboxes, then try checking if your class is at all available on 
Code:
loader.content.loaderInfo.applicationDomain.hasDefinition("fully.qualified.ClassName");

_________________
http://www.couchsurfing.com/people/wvxvw



 
 
 Re: problem with getDefinitionByName
If it works in "popup" mode (ie. Active X Flash player) and not in External (standalone Flash player) then you may need to download a more recent "Projector content debugger" (run once to associate with SWFs) from here:
http://www.adobe.com/support/flashplayer/downloads.html



 
 
 Re: problem with getDefinitionByName
I downloaded version 10.0.42.34 of Projector content debugger and still the same problem.
I downloaded, ran it once and then I test my movie. Debugger player runs, but the problem persists..

I also checked 

Code:
loader.content.loaderInfo.applicationDomain.hasDefinition("fully.qualified.ClassName");

which returned true. I don't know much about sandboxes but I suppose getting true was a good thing right? 

Something important to note is that my application is not indented to be online, I will create a cdrom which will only run locally, so I've never checked it in a browser. Trying to do so right now, produced the same error. I also don't have any idea about security sandbox issues, which I believe must be the source of my problem... 

I did some more tests and I think its something about local-file-access-sequrity settings that I don't know about?
What I used to do that worked in Flash IDE was to have an fla inside my src folder and then load some .swf and .xml from other folders.
Now that the .swf goes into the /bin folder everything is messed up. I tried to take a working swf produced by the .fla from the /src folder and run it in the bin folder and the same error appeared.

I also tried taking the /bin .swf produced by FD and running it elsewhere and I got a

Code:
/mySwf.swf cannot access local resource file:///myPath/assets/xml/info.xml. Only local-with-filesystem and trusted local SWF files may access local resources.


Could it be that I previously had everything inside one folder while now I have to access files in parent folders which triggers sequrity sandox errors??

I'm so confused 



 
 
 Re: problem with getDefinitionByName
Yes this is a local security issue. This does not happen when you test a swf from Flash CS or in FD in the Popup or Document viewer.

When FD compiles a SWF (using the Flex SDK) it will white-list the /bin directory (local security is path-based).

If you need to manually add a directory to the security white-list then you can either:
- use the global security panel:
http://www.macromedia.com/support/docum ... ger04.html
- or FD's "Files Panel": browse to the directory you want to white-list, select the folder or any file it contains and right-click > Add to Trusted Paths

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://stackoverflow.com/questions/7863271/as3-access-function-in-external-class-located-in-external-swf

 

AS3: Access function in external class located in external swf

I am trying to access a function in a loaded swf that has external class.. I would like to avoid having to put the function on my "Main" Doc class in the external swf and instead access the function directly from the class
This is what ive tried so far and it's a no dice:
This is the function in com.view.Creative.as
//Returns "ReferenceError: Error #1069: Property setVar not found on com.view.Creative and there is no default value."
This is the other approach I took with no success
This is the function in com.view.Creative.as
//Returns "ReferenceError: Error #1069: Property setVar not found on com.view.Creative and there is no default value. at com.util::ClickArea/completeHandler()"
There's gotta be a solution for this.....Thanks in advanced!
actionscript-3 oop class dynamic
 

1 Answer

activeoldestvotes

in second case try this :
event.target is Your contentLoaderInfo .
If You loading swf into new ApplicationDomain , You cannot look for definition in currentDomain .
in first case , maybe You already have class Creative under this alias but with different params and when You load swf to currentDomain , class :"com.view.Creative" will not overwrite existing , but return class from main swf.
 

 

 

=================================

=================================

=================================

 

 

 

반응형


관련글 더보기

댓글 영역