*1  *2 

AIR 한글 텍스트 삭제 버그 수정 - 2

일단 코드부터 보기로 하자



그렇다.. 저번 보다 코드가 엄청 복잡해 졌다.

사실 말이야 바른 말이지,

뭔가를 제대로 하려면

코드는 대개 복잡해 지기 마련이다.

문제를 요약하면 이렇다.

사실, TextField의 keyDown 이벤트는

실제 보이는 한글 글자를 반영해 주지 못한다.

실제 보이는 한글 글자를 반영해 주는 건

keyUp 이벤트이다.

따라서, 만일 사용자가 희덕님의 지적대로

키보드를 꾹 누르고 안 떼면

keyUp 이벤트는 한 번도 발생하지 않고

이렇게 되면, 개발자는 정말 어둠속을 헤매야 한다.

실제 반영된 글자를 알 수 없는 상황에서 어둠속을 헤집고 다니듯이

글자를 처리해 줘야 하니까 말이다.

그래서 나는 이 문제를 도대체 어떻게 해결해야 할까 고민에 고민을 거듭했다.

그래서 내린 결론이

두 개의 플래그를 추가해서

하나는 keyDown 이벤트에 쓰고

다른 하나는 keyUp 이벤트에 쓰는 방식이다.

이렇게 하면 두 이벤트가 서로 충돌하지 않으면서

keyDown 이벤트는 keyDown 이벤트의 기능을 하게 되고

keyUp 이벤트는 keyUp 이벤트의 기능을 할 수 있게 된다.

keyUp 이벤트를 처리하는 upHandler는 사용자가 글자를 한 글자씩 백스페이스를 눌러서

제거할 때 사용된다.

반대로 keyDown 이벤트는 사용자가 백스페이스를 계속 누르고 있을 때 사용된다.

이 때 keyDown 이벤트에서는 단 한번만 selection을 우측으로 1 이동시킴으로써

글자를 지우기 시작한 지점 이후에 나오는 다른 글자들이

지워지지 않도록 했다.
 
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/12/03 02:26 2008/12/03 02:26
REPLY AND TRACKBACK RSS http://joshy21.com/weblog/rss/response/47
REPLY AND TRACKBACK ATOM http://joshy21.com/weblog/atom/response/47
TRACKBACK ADDRESS
http://joshy21.com/weblog/trackback/47
REPLY RSS http://joshy21.com/weblog/rss/comment/47
REPLY ATOM http://joshy21.com/weblog/atom/comment/47
wrote at 2008/12/03 13:54
멋지십니다 -_-b
eirene 
wrote at 2008/12/05 01:58
모 허접합니다.. ㅠㅠ
wrote at 2009/01/09 01:07
감사합니다 ^^
근데, styleName에 이름을 적으니 var tf:UITextField = txt.getChildAt(1) as UITextField; 부분에서 tf가 null이 되더라구요.
잘 몰라서-_- var tf:UITextField = UITextField(this.textField); 이렇게 하니까 되더라구요. 왜그럴까요? ㅠㅠ
eirene  
wrote at 2009/01/10 10:01
으흐흐... 저건 그냥 말하자면, 러프하게 만든 코드이고, 실제 적용하실 때는 TextInput이나 TextArea 클래스를 상속해서 내부 UITextField를 직접 제어하시는 게 좋을 거 같습니다 ^^
wrote at 2009/01/11 02:17
헉...바보같은 짓을 해버렸네요-_-;
사실 상속받았는데 이런 코드를 사용했네요-_-;
var tf:UITextField = UITextField(this.textField);
그냥 this.textField.addEventListener하면 되는데-_-;
감사합니다 ^^
eirene  
wrote at 2009/01/13 13:47
var tf:UITextField = UITextField(this.textField);
일케 안해도 그냥 this.textField.addEventListener~
이런 식으로 하셔도 됩니다 ㅇㅇ
[로그인][오픈아이디란?]
이름 :
비밀번호 :
홈사이트 :
비밀글 :

AIR 1.1 이후 한글 입력 버그 수정하기

문제점 : AIR 1.1 이후 한글 입력시 글자를 지우기 시작한 글자의 초성이 잘 삭제되지 않는 버그가 있다.

해결책 : 내부 TextField 객체에 접근해 커스텀 이벤트 핸들러를 추가하고, 특정 조건에 따라 초성을 강제 삭제하도록 한다.

이 문제는 꽤나 중요한 문제로 AIR 1.0 버전에서는 없던 문제이다. 

나는 이 문제에 대해 어도비사에 공식적으로 버그 리포팅을 한 적이 있고,

나뿐 아니라, 이희덕님이나 다른 여러 한국 개발자들도 이 문제에 대한 버그 수정을

어도비에 요구한 것으로 알고 있다.

그런데, 방금 전에 플렉스로 잠깐 코딩을 해 보니, 

이 문제는 의외로 간단하게 해결할 수 있다.

TextInput과 같은 컨트롤 내부에 있는 텍스트 필드에 접근해

이벤트 리스너를 추가하고, 특정 조건에 따라 

초성을 제거하면 되기 때문이다.

이 때 특정 조건은 다음과 같다.

1. keyUp 이벤트가 일어날 때마다 이전 문자열을 전역 변수에 저장해 놓는다.

2. 백스페이스를 누른 상태에서 현재 텍스트필드의 텍스트와 이전 텍스트가 같은지

확인한다. 이 때 혹시 뒤에 공백이 있을 수 있으므로, 공백을 제거한 문자열을 비교한다.

3. 만일 두 텍스트가 같다면, 이것 참 이상한 일이다. 어떻게 두 문자가 같을 수 있을까? 분명히 백스페이스를 눌렀는데 말이다!!!

4. 이런 경우는 백 스페이를 누른 위치를 기준으로 앞의 문자열과 뒤의 문자열을 잘라 새로운 텍스트를 텍스트 필드의 텍스트로 집어 넣는다. 이렇게 하는 이유는, 꼭 마지막 글자에서 백스페이스를 눌러서 글자를 지우지 않더라도, 글자 중간에 커서를 이동해 글자 중간부터 쓰다가 다시 글자 중간부터 지울 경우도 대비하기 위해서이다.

5. 이제 버그 없는 텍스트 인풋 컨트롤을 맘껏 사용한다.


물론 실제로 현업에서는 이렇게 애플리케이션 단에서 코딩을 하면 안된다. 

방법은 두 가지가 있을 수 있는데, 

하나는 TextInput이나 TextArea를 상속해 이 클래스에 위와 같은 로직을

추가하는 방식이고,

다른 하나는 유틸리티 클래스를 만들어서 TextInput 등의 컨트롤을 입력받아 

이런 로직을 처리하도록 하는 방식이다. 

두 방식 중 어떤 것을 사용해도 상관은 없겠지만,

기왕이면 전자의 방식이 보다 OOP 설계에 맞다고 할 수 있다. 

액션스크립트 원리
: TextInput, Text, Label, TextArea 등의 컨트롤은 모두 TextField 인스턴스에 대한 래퍼클래스들이다. 이들 인스턴스 안에 있는 TextField 인스턴스에 접근하면, 한글의 자,모음을 하나씩 제어하는 게 가능하다. 



크리에이티브 커먼즈 라이센스
Creative Commons License
2008/11/27 03:10 2008/11/27 03:10
REPLY AND TRACKBACK RSS http://joshy21.com/weblog/rss/response/40
REPLY AND TRACKBACK ATOM http://joshy21.com/weblog/atom/response/40
TRACKBACK ADDRESS
http://joshy21.com/weblog/trackback/40
tracked from 희희덕하며 웃어보자
tracked from 우야꼬의 Adobe RIA
REPLY RSS http://joshy21.com/weblog/rss/comment/40
REPLY ATOM http://joshy21.com/weblog/atom/comment/40
wrote at 2008/11/27 16:31
이야! 킹왕짱 에어레네님!
멋지십니다 ㅋㅋㅋ
eirene 
wrote at 2008/11/27 20:11
저야 모 허접합니다 ㅇㅇ ㅠ
wrote at 2008/11/27 18:55
좋은팁 감사합니다. ^^
eirene 
wrote at 2008/11/27 20:12
맆흘 감사드립니다 (_ _)/
eirene 
wrote at 2008/11/28 01:00
살짝 버그가 있어서 수정했습니다.

생각해 보니, 공백을 제거한 문자열을 비교하는 건 맞지 않은 것 같고요 (이건 저의 판단 착오)

백스페이스 키를 계속 누르고 있을 경우를 대비해 keyDown 이벤트에도 이벤트 리스너를 추가했습니다.
wrote at 2008/12/02 01:01
저도 해결책을 찾아보다가 다른 방법을 찾게되서
맘에 들진 않지만 그래도 어느정도 쓸만한거 같아서 트랙백 걸었습니다^^
eirene 
wrote at 2008/12/02 22:52
다시 보니 여러가지 버그가 있네요... 제 소스도 수정해야 하고, 희덕님이나 우야꼬님 소스도 수정해야 될 듯 합니다 ^^;

일단 희덕님 소스의 문제점은, 중간부터 글자를 지울 경우 글자를 지우기 시작한 다음에 있는 글자도 함께 지워진다는 겁니다... 우야꼬님 소스도 마찬가지구요...

이런 이유로 setSeleciton 부분은 조심스럽게 접근해서 조건을 까다롭게 줘야 할 거 같습니다... 지금 이 버그를 수정중인데, 하나를 수정하면 하나가 말썽이네요 ㅎㅎ

대충 눈에 안 띄게 만들어 놓기는 했는데, 정리되면 공개하겠습니다 ㅋㅋ
[로그인][오픈아이디란?]
이름 :
비밀번호 :
홈사이트 :
비밀글 :

AIR와 웹 애플리케이션간 로컬 커넥션 통신하기

문제점 : 웹 애플리케이션에서 AIR 애플리케이션의 메소드를 호출하고 싶다.

해결책 : 로컬 커넥션을 사용해 두 애플리케이션간 통신하도록 하면 된다.

사실 누군가가 처음 내게 이 질문을 했을 때

난 별 생각없이, "물론, 로컬커넥션을 사용하면 웹 애플리케이션이랑 AIR 애플리케이션이

서로 통신할 수 있지"라고 대답했다.

그런데 가만 생각해 보니, 웹 애플리케이션은 플래시 플레이어에서 구동되고

AIR 애플리케이션은 AIR 런타임에서 구동되는데, 둘이 통신할 수 있다는 게

말이 안되는 거 같았다. 그래서 나는 대답을 보류했고, 한참 동안 관련 레퍼런스를

찾아서 결국 로컬 커넥션을 통한 통신이 가능하다는 것을 알아 냈다.

일단 웹 애플리케이션에서 AIR 애플리케이션에 접근하려면 다음 문법을 따라야 한다.

(이 때 lc는 LocalConneciton 인스턴스라고 가정한다)

lc.send("app#"+AIR 애플리케이션 ID+"."+AIR 애플리케이션 제작자(publisher) ID+":"+AIR 애플리케이션 로컬 커넥션 네임,"메소드 명", 파라미터)

얼핏 봐도 복잡해 보인다.

한편 반대로 AIR 애플리케이션에서 웹 애플리케이션의 메소드를 호출하려면

다음과 같이 해야 한다.

lc.send(웹 애플리케이션 도메인+":"+웹 애플리케이션 로컬 커넥션 네임,"메소드 명", 파라미터)

이 때 웹 애플리케이션 도메인은 로컬에 있을 때는 localhost,

웹 도메인에 있을 때는 도메인명(예를 들어,www.joshy21.com)이 된다.


사실 웹 애플리케이션과 AIR 애플리케이션 사이의 로컬 커넥션 통신을 통한 연동은

활용 범위가 엄청나게 넓다. 예를 들어, ActionScript 2와 AIR와의 통신도 가능하고

간단한 로컬 커넥션 핼퍼 클래스를 작성해 연동 부분만 처리하면,

웹 애플리케이션에서  launchApplication() 메소드를 통해 AIR 애플리케이션이 (실행중이 아니면) 실행시키고

서로 통신하면서 온갖 "쇼"를 다 할 수도 있을 것이다.

그래서 나는 다음과 같은 LocalConnection Info 클래스와 Manager 클래스를 만들어

AIR 애플리케이션과 웹 애플리케이션 사이의 연동이 정말 쉬워질 수 있도록 했다.

먼저 LCInfo 클래스의 소스는 다음과 같다.



이 클래스는 domain, air_connection, web_connection, isAirApp, appId, publisherId

속성을 가지고 있는데, 각각의 속성은 다음과 같다.

domain - 웹 애플리케이션이 있는 도메인 위치. 기본값은 localhost
air_connection - AIR 애플리케이션의 로컬 커넥션 네임
web_connection - 웹 애플리케이션의 로컬 커넥션 네임
isAirAipp - 해당 애플리케이션이 웹 애플리케이션인지 AIR 애플리케이션인지 여부
appId - (웹 애플리케이션인 경우에만) AIR 애플리케이션의 애플리케이션 ID
publisherId - (웹 애플리케이션인 경우에만) AIR 애플리케이션의 제작자 ID


이어서 이 클래스를 활용하는 메니저 클래스의 소스를 살펴보면 다음과 같다.


이 클래스는 싱글턴 패턴을 따르고 있고 LCInfo 클래스 인스턴스를

속성으로 가지고 있다 (has-a 관계).

하는 일은 애플리케이션이 웹 애플리케이션인지 AIR 애플리케이션인지

init() 메소드를 통해 알게 된 후

자동으로 상대편 애플리케이션에 로컬 커넥션의 send() 메소드를 통해

접근할 커넥션 네임을 생성해 주고

LCManager.getInstance().send() 메소드를 통해

굳이 로컬 커넥션 객체에 접근해 일일히 커넥션 네임을 할당하지

않아도 상대편 애플리케이션과 통신할 수 있도록 해 주는 기능이다.


그럼 이어서 예제를 보도록 하자.

AIR 애플리케이션 예제

웹 애플리케이션 예제
 

이 두 예제에서 하는 일은 다음과 같다.

AIR 애플리케이션에서는 LCManager 클래스를 통해 로컬 커넥션을

생성하고 웹 애플리케이션쪽으로 애플리케이션 ID와 publisher ID를

타이머를 통해 전송해 준다.

웹 애플리케이션에서는 역시 LCManager 클래스를 통해 로컬 커넥션을

생성하고 AIR 애플리케이션에서 호출하는 getID 메소드를 통해

AIR 애플리케이션의 ID와 publisher ID를 동적으로 전달받는다.

이렇게 전달받은 애플리케이션 ID와 publisher ID를 바탕으로

웹 애플리케이션은 AIR 애플리케이션의 stopTimer() 메소드를

LCManager 클래스를 통해 호출하고


AIR 애플리케이션의 타이머는 멈추게 된다. 또 test 버튼을 클릭하면 AIR 애플리케이션의 showAlert 메소드에 파라미터를 넘겨서 AIR 애플리케이션의 메소드를 파라미터와 함께 호출하도록 한다.  

웹 애플리케이션 메소드

AIR 애플리케이션 메소드

액션스크립트 원리 : LocalConnection 객체를 사용하면 서로 다른 도메인의 두 swf간 통신은 물론 AIR 애플리케이션과 웹 애플리케이션, AIR 애플리케이션과 또 다른 AIR 애플리케이션 간의 통신이 가능하다. 하지만 로컬 커넥션은 하나의 커넥션 네임당 하나의 애플리케이션만 허용되는 점, 호출할 메소드가 public으로 선언되어야 한다는 점 등 몇 가지 제약이 따르니 사용시에는 항상 주의가 필요하다.
크리에이티브 커먼즈 라이센스
Creative Commons License
2008/11/07 22:15 2008/11/07 22:15
tagged with  ,
REPLY AND TRACKBACK RSS http://joshy21.com/weblog/rss/response/30
REPLY AND TRACKBACK ATOM http://joshy21.com/weblog/atom/response/30
TRACKBACK ADDRESS
http://joshy21.com/weblog/trackback/30
REPLY RSS http://joshy21.com/weblog/rss/comment/30
REPLY ATOM http://joshy21.com/weblog/atom/comment/30
wrote at 2008/11/09 03:48
^^ 좋은 글 잘봤습니다.
swf가 web에 embed딘 상태에서 직접 테스트 하신건가요?
왜 이질문을 드렸냐면....
AIR와 swf간의 통신때는 LocalConnection 의 채널명이 언더스코어(_)로 시작하지 않으면 통신이 안되기 때문입니다..
예전에 구현을 하다 한참을 헤맨 부분이었지요.... AIR Developer Center에서 답을 찾고 난후 얼마나 허무하던지.. :)

그럼 좋은 하루 되세요.~
eirene 
wrote at 2008/11/09 08:46
네~ 아예 swf가 들어있는 html 페이지를 플렉스의 HTML 컴포넌트를 써서 로드해서 테스트해 본 겁니다.. 물론 웹에 임배드된 상태에서도 해 봤구요^^ 언더스코어 얘기는 첨 듣네요 ^^; 제가 잘 모르는 걸 수도 ㄷㄷㄷ ㅠ
eirene 
wrote at 2008/11/09 20:38
AIR에서 HTML 컴포넌트 써서 불러오지 않고 그냥 브라우저에서 웹 애플리케이션 띄우고 AIR에서 언더스코어 안 쓰고 로컬 커넥션으로 연동해 봤는데 잘 되네요^^
wrote at 2008/11/10 10:29
RSS주소가 바뀌었군요. 어쩐지 언제부터인가 rss에서 에러가 나더니...-_-;
암튼 좋은 내용 잘 봤습니다 ^^ 시도중입니다 ㅠ
eirene 
wrote at 2008/11/10 12:17
헐.. 그런가요 ㅠㅠ 제가 Textcube 업뎃하면서 몬가 실수를 했나 보네여 ㄷㄷㄷ ㅠ
wrote at 2008/11/16 16:23
좋은 글 잘봤습니다.
wrote at 2008/11/27 00:06
우와 +_+ ; 그렇군요 ~ ㅋ 정말 감사합니다.
재밌는거 많이 만들 수 있을꺼 같아 흥미진진해지네요 ^-^
아바 
wrote at 2009/12/05 23:10
좋은 정보 정말 감사합니다!!
[로그인][오픈아이디란?]
이름 :
비밀번호 :
홈사이트 :
비밀글 :
*1  *2 
count total 10250, today 15, yesterday 18
관리인 : eirene
rss
I am
전체
Development
La vie quotidienne
English
Languages
Jesus
글 보관함
2010/01, 2009/06, 2009/03, 2009/02, 2009/01,
달력
«   2010/03   »
  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