감사합니다 ^^
근데, styleName에 이름을 적으니 var tf:UITextField = txt.getChildAt(1) as UITextField; 부분에서 tf가 null이 되더라구요.
잘 몰라서-_- var tf:UITextField = UITextField(this.textField); 이렇게 하니까 되더라구요. 왜그럴까요? ㅠㅠ
헉...바보같은 짓을 해버렸네요-_-;
사실 상속받았는데 이런 코드를 사용했네요-_-;
var tf:UITextField = UITextField(this.textField);
그냥 this.textField.addEventListener하면 되는데-_-;
감사합니다 ^^
article id #40 categorized under Development/AIR & written by eirene
문제점 : AIR 1.1 이후 한글 입력시 글자를 지우기 시작한 글자의 초성이 잘 삭제되지 않는 버그가 있다.
해결책 : 내부 TextField 객체에 접근해 커스텀 이벤트 핸들러를 추가하고, 특정 조건에 따라 초성을 강제 삭제하도록 한다.
이 문제는 꽤나 중요한 문제로 AIR 1.0 버전에서는 없던 문제이다.
나는 이 문제에 대해 어도비사에 공식적으로 버그 리포팅을 한 적이 있고,
나뿐 아니라, 이희덕님이나 다른 여러 한국 개발자들도 이 문제에 대한 버그 수정을
어도비에 요구한 것으로 알고 있다.
그런데, 방금 전에 플렉스로 잠깐 코딩을 해 보니,
이 문제는 의외로 간단하게 해결할 수 있다.
TextInput과 같은 컨트롤 내부에 있는 텍스트 필드에 접근해
이벤트 리스너를 추가하고, 특정 조건에 따라
초성을 제거하면 되기 때문이다.
이 때 특정 조건은 다음과 같다.
1. keyUp 이벤트가 일어날 때마다 이전 문자열을 전역 변수에 저장해 놓는다.
2. 백스페이스를 누른 상태에서 현재 텍스트필드의 텍스트와 이전 텍스트가 같은지
확인한다. 이 때 혹시 뒤에 공백이 있을 수 있으므로, 공백을 제거한 문자열을 비교한다.
3. 만일 두 텍스트가 같다면, 이것 참 이상한 일이다. 어떻게 두 문자가 같을 수 있을까? 분명히 백스페이스를 눌렀는데 말이다!!!
4. 이런 경우는 백 스페이를 누른 위치를 기준으로 앞의 문자열과 뒤의 문자열을 잘라 새로운 텍스트를 텍스트 필드의 텍스트로 집어 넣는다. 이렇게 하는 이유는, 꼭 마지막 글자에서 백스페이스를 눌러서 글자를 지우지 않더라도, 글자 중간에 커서를 이동해 글자 중간부터 쓰다가 다시 글자 중간부터 지울 경우도 대비하기 위해서이다.
5. 이제 버그 없는 텍스트 인풋 컨트롤을 맘껏 사용한다.
물론 실제로 현업에서는 이렇게 애플리케이션 단에서 코딩을 하면 안된다.
방법은 두 가지가 있을 수 있는데,
하나는 TextInput이나 TextArea를 상속해 이 클래스에 위와 같은 로직을
추가하는 방식이고,
다른 하나는 유틸리티 클래스를 만들어서 TextInput 등의 컨트롤을 입력받아
이런 로직을 처리하도록 하는 방식이다.
두 방식 중 어떤 것을 사용해도 상관은 없겠지만,
기왕이면 전자의 방식이 보다 OOP 설계에 맞다고 할 수 있다.
액션스크립트 원리 : TextInput, Text, Label, TextArea 등의 컨트롤은 모두 TextField 인스턴스에 대한 래퍼클래스들이다. 이들 인스턴스 안에 있는 TextField 인스턴스에 접근하면, 한글의 자,모음을 하나씩 제어하는 게 가능하다.
활용 범위가 엄청나게 넓다. 예를 들어, 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으로 선언되어야 한다는 점 등 몇 가지 제약이 따르니 사용시에는 항상 주의가 필요하다.
^^ 좋은 글 잘봤습니다.
swf가 web에 embed딘 상태에서 직접 테스트 하신건가요?
왜 이질문을 드렸냐면....
AIR와 swf간의 통신때는 LocalConnection 의 채널명이 언더스코어(_)로 시작하지 않으면 통신이 안되기 때문입니다..
예전에 구현을 하다 한참을 헤맨 부분이었지요.... AIR Developer Center에서 답을 찾고 난후 얼마나 허무하던지..