노무현 대통령 배너

AS3.0 로더(Loader)로 불러온 다른 swf 의 클래스 사용하기

by 세계의끝 on 7.05, 2009, under AS3.0

blue_swf_icon이 문제는 AS3.0 의 swf 간 로드 구조를 구성할 때 반드시 한번은 만나게 되는 문제이므로 정리해 둡니다.

Main.swf 에서 Sub.swf 를 Loader 를 이용해 로드한 후에 Main.swf 에서 Sub.swf 의 클래스나 메서드를 사용해야 할 때가 있습니다.

AS2.0 라면 MovieClipLoader 와 loadClip 을 이용하여 로드 완료 이벤트를 확인 한 후 인스턴스네임으로 참조해 들어가면 되지만, AS3.0의 경우에는 그런 방법으로 다른 swf의 클래스를 사용할수 없습니다. 이런 경우 ApplicationDomain 클래스의 getDefinition() 메서드를 이용해 참조해야 합니다.

이 예제에는 3개의 클래스가 사용됩니다. 각 클래스에 대한 설명은 본문과 코드 주석에 포함되어 있습니다.

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// SubSystem.as 의 내용.
package
{
	import flash.display.Sprite
 
	/*
	 * 이 클래스는 별도로 SubSystem.swf로 컴파일 하여 Main.swf 에서 Loader를 통해 로드하는 대상으로 삼음
	 * 즉, 이 클래스는 SubSystem.swf 의 도큐먼트 클래스 입니다.
	 */
	public class SubSystem extends Sprite
	{
		public function SubSystem()
		{
			trace( "SubSystem !!!" )
		}
 
		public function createItem( $name:String = "" ):Sprite
		{
			var item:Circle = new Circle( $name, 50, 50 );
			addChild( item )
			return item;
		}
	}
}

생성자에서는 제대로 로드가 되었는지 확인하는 용도의 trace 외에는 하는 일이 없고, public 으로 공개된 createItem() 메서드는 Circle 클래스를 new 해주고, 객체를 반환하고 있습니다.

Circle 클래스는 예제용으로 밖에 사용할 일이 없는 궁극의 원그리기 클래스 입니다.

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Circle.as 의 내용.
package
{
	import flash.display.Sprite
 
	public class Circle extends Sprite
	{
		private var _name:String;
 
		public function Circle( $name:String = null, $x:int = 0, $y:int = 0, $radius:uint = 50, $color:uint = 0x000000, $alpha:Number = 1 )
		{
			draw( $x, $y, $radius, $color, $alpha )
			this._name = $name
		}
		private function draw( $x:int, $y:int, $radius:uint, $color:uint, $alpha:Number ):Sprite
		{
			var item:Sprite = new Sprite();
			item.graphics.beginFill( $color, $alpha );
			item.graphics.drawCircle( $x, $y, $radius );
 
			addChild( item )
			return item
		}
 
		override public function get name():String { return _name; }
	}
}

SubSystem 클래스에서 Circle 클래스를 따로 import 하지 않았으므로, 이 두개의 클래스는 같은 폴더에 넣어야 동작하겠군요.

다음은 Main 클래스 입니다. 이 파일은 Main.swf 에 사용되는 도큐먼트 클래스 입니다.

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Main.as 의 내용.
package
{
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;
 
	public class Main extends Sprite
	{
		private var loader:Loader = new Loader();
		private var request:URLRequest = new URLRequest( "SubSystem.swf" );
 
		public function Main()
		{
			//Loader는 직접 addEventListener 하지 못하고 contentLoaderInfo 를 통하여야 함
			loader.contentLoaderInfo.addEventListener( Event.COMPLETE, completeHandler );
			loader.load( request );
		}
 
		private function completeHandler( e:Event ):void
		{
			var runtimeClassRef:Class = loader.contentLoaderInfo.applicationDomain.getDefinition( "SubSystem" )  as  Class;
			var displayObj:DisplayObject = new runtimeClassRef(); //addChild 하려면 DisplayObject 로 캐스팅
			addChild( displayObj );
 
			var subSystemObj:Object = displayObj as Object; //메서드를 호출하려면 다시 Object 로 캐스팅
			var item1:Sprite = subSystemObj.createItem( "item1" );
			var item2:Sprite = subSystemObj.createItem( "item2" );
			item2.x = 100;
 
			//로드한 SubSystem.swf 의 자원은 이제 subSystemObj 로 참조하면 됩니다.
			trace( "subSystemObj.numChildren : ", subSystemObj.numChildren );
		}
	}
}

getDefinition() 과는 직접 관련은 없지만, 한가지 짚고 넘어가야할 내용이 있습니다. Loader 의 다운로드 진행상황이나 로드 완료 등의 이벤트를 받고 싶을 경우 Loader 에 contentLoaderInfo 를 통해 addEventListener 를 걸어야 합니다.[01] Loader 에 직접 addEventListener 를 걸고 아무리 기다려본들 이벤트는 발생하지 않습니다.[02]

다시 내용으로 돌아와서, Main.as 는 SubSystem.swf 를 Loader 를 통해 로드하고, 로드 완료된 이벤트 확인한 이후, SubSystem 의 내부 메서드를 호출하여 SubSystem 로 하여금 Circle 객체를 new 로 생성하게 하고 있습니다.

만약 SubSystem.swf 를 통해 얻고 싶은 것이 fla의 라이브러리에 Class 네임으로 정의한[03] 무비클립이라면 getDefinition( “ClassName” ) 과 같이 해당 무비클립의 클래스 네임을 넣어주고 addChild 까지만 해주면 됩니다. 메서드 호출 까지도 필요 하지 않은 경우라면 이렇게 훨씬 더 간단하죠.

참고 : Main.swf 가 AS3.0 이고 SubSystem.swf 가 AS2.0 인 경우 ApplicationDomain 은 사용할 수 없습니다.

관련 레퍼런스 링크
ApplicationDomain 클래스 사용
ActionScript 3.0 언어 및 구성 요소 참조 설명서 : ApplicationDomain

* 다른 swf 가 아닌 하나의 swf에서 fla 라이브러리에 정의한 클래스 이름으로 무비클립을 사용하려면 “AS3.0 getDefinitionByName() 메서드를 이용한 라이브러리 자원 이용 – AS2.0 attachMovie 대응” 을 읽어보세요..

  1. 로더객체.contentLoaderInfo.addEventListener(……) []
  2. 로더객체.addEventListener(……) <– (잘못된 사용) []
  3. AS2.0의 Linkage 사용하듯 []

관련된 글

:, , , , , , , , , , , , ,

7 Comments for this entry

  • No Gravatar

    안녕하세요? 배우러 들렀다 질문드립니다. ㅎ

    첫째는,
    위에 main.as에서 클래스 정의한 부분 …….. getDefinition(‘SubSystem’)
    여기에서 “SubSystem” 요게 클래스 이름이잖아요.
    그럼 메인타임라인에 그냥 코딩해서 만든 swf는 위 방법으론 클래스화 안되는건가요?

  • No Gravatar

    둘째는, 좀 관계없는 초급 질문인데
    예를 들어 맨위에 작성한 SubSystem 클래스를 도큐먼트 클래스로 하여 swf 만들때
    전 여태까지 메인타임 라인에서
    클래스 생성후 addChild 해줬었거든요.
    flash ide(CS4)에서 이 방법 말고 다른 간단한 방법이 있는지요?
    죄송하게도 항상 질문만 남기고 가네요 ㅡㅡ;
    수고하세요 ^^ (코드를 쓰니깐 에러가 나네요..)

    • 세계의끝No Gravatar

      이 질문은 목적어와 주어가 다수 생략된것 같아, 무슨 의미인지 이해가 잘 가질 않는군요 ^^

      • No Gravatar

        아.. 요건 창피해서 다시 말씀 못드리겠네요. 하하
        그냥 클래스 이름을 써넣으면 되는거였는데 암튼 혼자 해결했답니다.

  • 궁금이No Gravatar

    수고많으십니다.~ 답변이 있었으면 하는 바램입니다.

    상황은 제가만드는 플래시에 ~ loader로 다른 swf를 불러야하는상황입니다.
    헌데 이 swf는 소스도 없고, 안에 아무것도 모르는 상황입니다. 클래스라든가뭐그런거등등아무것도….

    헌데 textfield 가 있더군요.
    그래서~ loader로 불러 이로드에 addEventliastener(마우스.click 을 했더니)
    오~ textfield 에 값이 trace로 나오긴하더군요…

    혹시 ~이런상황에서 저 textfield 의 값을 제가 빼올수있을까요?
    개발자입니다만 플래시를 잘몰라서요.
    이벤트발생시키고 관련 함수를 실행시키게 되어있던데
    그안에 e.target.text하니까 일단 textfield 의 글을 가져오기는하는데~ 난감합니다.

    • 세계의끝No Gravatar

      그러니까 TextField 객체의 인스턴스네임을 알고 싶다는 질문이죠?

      만약 swf 파일에 있는 텍스트필드가 스테이지에 텍스트 툴로 그려진 후 인스턴스네임이 지정된 녀석이라면 클릭이벤트의 e.target.name 로 인스턴스네임을 알 수 있습니다.
      name 이 인스턴스네임은 아니지만, 플래시의 저작툴로 텍스트필드를 만든 경우에는 Flash IDE가 인스턴스네임을 지정하면서 name 속성에도 같은값을 넣어주기 때문입니다.

      그런데 위의 경우가 아니고

      0
      1
      
      var tf:TextField = new TextField();
      addChild( tf );

      위와 같은 형태로 액션스크립트에서 런타임에 만들어진 텍스트필드라면 핸들링을 할 수 있는 인스턴스네임을 알 수 있는 방법이 없습니다.
      대부분의 경우 instance1, instance2 … 같은 형태로 자동 지정되기 때문이죠.

      다만, 클래스에서 전역변수로 정의되어있다면 디컴파일러로 변수명은 알 수 있습니다만, 다른 swf 파일을 Loader 로 가져온 경우에는 단순히 변수명으로는 객체를 참조를 할 수 없으므로 무용지물이 되겠습니다.

      그러나 역시 가장 흔한 경우가 첫 번째 경우이므로 name 이 뭔지 찍어보세요.

1 Trackback or Pingback for this entry

Leave a Reply

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!