scaleform.minarto.com

Object.watch 를 이용한 데이터 바인딩 1 본문

Communication

Object.watch 를 이용한 데이터 바인딩 1

미나토 2012. 4. 10. 18:26


http://scaleform.minarto.com/335

에 이어지는 글입니다


앞선 포스팅에서 watch 의 단점으로 하나의 속성에 하나의 핸들러만 연결할 수 있다고 했습니다.

레퍼런스에는 


"단일 감시점만 속성에 등록될 수 있습니다. 같은 속성에 대해 이후에 Object.watch()를 

호출하면 원래 감시점이 바뀝니다."


라고 쓰여있네요...


뭐, 그래봤자 해결 방법은 사실 너무 간단합니다.


var o = {level:1};

o.watch("level", hn);

function f0($n):Void{

trace("f0 : " + $n)

}

function f1($n):Void{

trace("f1 : " + $n)

}


function hn($p, $o, $n):Void{

f0($n);

f1($n);

}

o.level = 4;


이 정도 코드면 되는 것이죠...

해당 키값의 핸들러에 여러 함수를 실행시키도록 하면 되는 겁니다.


자, 이제 이걸 범용적으로 쓸 수 있도록 바꿔보겠습니다.


일단 함수 정의는 다음과 같습니다.


function addBinding($keyScope, $key:String, $handlerScope, $handler:String)


$keyScope 는 대상 객체입니다.

$key는 대상 객체의 감시할 키(속성)이죠...

$handlerScope, $handler 는 as2 용 EventDispatcher 를 사용해보셨으면 당연히 아시겠죠?

핸들러를 실행할 객체와 해당 핸들러명입니다.

addEevntListener 처럼 쓰는 것이죠...


var runData:Array = [];

배열을 하나 만들어야 합니다. 이 배열은 해당 키값의 핸들러에서 실행하게 될 함수들의 모음입니다.

그 배열에는 당연히 등록할 함수의 스코프와 함수명을 넣어야 합니다.

결국 이런 식이 되겠죠.

var runData:Array = [$handlerScope, $handler];


핸들러도 만들어야 하겠죠.


function($p:String, $oldValue, $newValue, $runData:Array){

var c:Number = $runData.length;

for (var i:Number = 0; i < c; i += 2) {

$runData[i][$runData[i + 1]]( $newValue );

}

return    $newValue;

}


이정도면 되겠죠...

참고로 레퍼런스에도 나와있지만 핸들러의 반환값이 다시 해당 키의 값으로 들어가기 때문에 $newValue 를 반환해주도록 짜는 것이 좋습니다.


이제 watch 로 연결합니다.

$keyScope.watch($key, function, runData);


끝났습니다... 뭔가 아쉽죠?


function addBinding($keyScope, $key:String, $handlerScope, $handler:String) {

var runData:Array = $keyScope.__watchRunData__;

if (runData) {

var c:Number = runData.length;

for (var i:Number = 0; i < c; i += 2) {

if (runData[i] === $handlerScope && runData[i + 1] == $handler) {

return;

}

}

runData.push($handlerScope, $handler);

}

else {

runData = [$handlerScope, $handler];

$keyScope.__watchRunData__ = runData;

}

if (!$keyScope.__watchHandler__) {

$keyScope.__watchHandler__ = function($p,  $oldValue ,  $newValue , $runData){

c = $runData.length;

for (i = 0; i < c; i += 2) {

$runData[i][$runData[i + 1]]( $newValue );

}

return    $newValue;

}

}

$keyScope.watch($key,  $keyScope.__watchHandler__, runData);

return $objectScope[$key];

}



자, 풀코드입니다~ 

물론 저는 더 개선해서 사용하고 있고.... 이놈은 블로그로 코딩(?)한거라 어딘가 오류가 있을지도...


다른 코드에서 참조하기 힘들도록 runData 와 function 의 이름에 __watchRunData__,  __watchHandler__ 같은 이름을 썼습니다.


이렇듯 Object 에 마음껏 속성이든 function 이든 붙일 수 있는 것이 as2의 특성이죠...


var player = {};

player.level = 0;

addBinding(player, "level", this, "f");

addBinding(player, "level", this, "f2");


function f($n):Void{

trace(1 + ":" + $n);

}

function f2($n):Void{

trace(2 + ":" + $n);

}


player.level = 1;


이런 간단한 예를 돌려보면 f, f2 두 함수 모두 실행되는걸 확인할 수 있을 겁니다.


이번 포스팅에는 실제 코드를 좀 과하게 넣었더니, 포스팅이 좀 길어졌네요...


as2 / js 란 언어의 특징을 잘 모르시는 분은 조금 코드가 어려울 지도 모르겠습니다.



하지만 어려워도 뭔가 좀 아쉽습니다... 그건 다음 포스팅으로 넘어가죠...


http://scaleform.minarto.com/343 으로 이어집니다



p.s. 오늘은 4월 11일 총선.... 투표합시다~!!!