8월 타이타늄 커뮤니티 티타임 후기

오랜만에 티타임을 가졌다. 하루 밖에 안지났는데,.. 벌서 기억나지 않는 것들이 너무 많다.. -_-;;.. 일단 생각나는 대로 정리!

Alloy 이슈들

Alloy 1.2 버전부터 ListView를 XML로도 정의할수 있게됐다. 물론 ListView는 아직 한창 개발중이기 때문에 drag 이벤트라든가 headerView나 Pulldown Refresh 기능들은 좀더 기다려야한다. 자세한 내용은 Alloy Jira 페이지를 확인해보자.

ListView에 데이터 바인딩시 삽질하기 쉬운 착각들

1. 먼저 dataCollection은 ListView가 아닌 ListSection에 정의해야한다.

이 문제 때문에 삽질한 시간은 정말 눈물 겹다. TableView의 경우 dataCollection을 TableView에 정의 하지만 ListView 조금 다르다. 다음 예제를 보자. 아래와 같이 ListView에 dataCollection을 정의하면 Alloy 컴파일 오류를 발생시킨다.

<ListView dataCollection='잘못된정의'>
    <Templates>
        <!-- 여기에 여러 템플릿을 정의 할수있다. -->
        <ItemTemplate name="tpl1" />
        <ItemTemplate name="tpl2" />
    </Templates>
    <ListSection></ListSection>
</ListView>

따라서 dataCollection은 반드시 아래와 같이 ListSection에 정의하도록 하자!! dataCollection으로 지정된 값은 models 폴더에 정의된 파일명과 동일한 콜랙션을 바인딩하게 된다. 아래 예제는 posts 콜랙션을 리스트뷰 템플릿에 바인딩하게 된다.

<ListView> 
    <Templates> 
        <ItemTemplate name="tpl1"></itemtemplate> 
        <ItemTemplate name="tpl2"></itemtemplate> 
    </Templates> 

    <!-- 데이터 바인딩시 dataCollection 속성은 필수 인자다. -->
    <ListSection dataCollection='posts'></ListSection>   
</ListView>

2. dataTransform과 dataFilter 속성의 차이점.

데이터 바인딩시 dataCollection 속성과 더불어 설정할 수 있는 2가지 속성이 더 있는데, 바로 dataTransformdataFilter 속성이다. 이 두 속성은 모두 아래와 같이 함수를 지정해야한다.

<ListView> 
    <Templates> 
        <ItemTemplate name="tpl1"></itemtemplate> 
        <ItemTemplate name="tpl2"></itemtemplate> 
    </Templates> 

    <!-- 데이터 바인딩시 추가로 dataTransform과 dataFilter를 지정할 수 있다. -->
    <ListSection dataCollection='posts' dataTransform='doTransform' dataFilter='doFilter'>
    </ListSection>   
</ListView>

두 함수의 차이는 간단하다. dataTransform 속성은 ItemTemplate에 데이터를 입힐 때 실행되는 함수로써 바인딩되는 콜렉션의 모델을 인자로 받아 가공할수있다. 반면에, dataFilter는 콜랙션 자체를 필터링 할때 사용한다.

3. 데이터 바인딩시 반드시 ListSection에 ListItem을 지정해라!

흔히 착각하는 것중에 하나가 ListSection을 비워두면 “초기에 아무런 값이 없고 나중에 동적으로 채워 넣을수 있겠지?” 하는 생각인데, ListView 자체를 컨트롤러에서 동적으로 직접 create해서 생성하는 경우에는 맞는말이다. 하지만 데이터 바인딩을 한 경우에는 반드시 아래와 같이 ListItem을 지정해야하고, 이렇게 지정된 녀석이 콜렉션의 갯수만큼 반복 된다는 사실을 잊지말자!

<ListView> 
    <Templates> 
        <ItemTemplate name="tpl1"></itemtemplate> 
        <ItemTemplate name="tpl2"></itemtemplate> 
    </Templates> 
    <ListSection dataCollection='posts' dataTransform='doTransform' dataFilter='doFilter'>
        <!-- 콜랙션을 반복하면서 아래에 정의된 아이템을 한벌로 생성한다. -->
        <ListItem template="tpl1"/>  
        <ListItem template="tpl2"/>
    </ListSection>   
</ListView>

성능 이슈

Alloy 이외에 일반적인 성능과 관련된 이야기들이 있었다. 정리하면 다음과 같다.

1. class 아니죠! className 입니다.

TableViewRow의 속성으로 같은 템플릿으로 구성되는 행들을 같은 className으로 지정해야 내부적으로 재활용하게 된다. class와 className을 헷갈리는 경우가 있으니 철자에 주의하자!

2. 디바이스 정보를 얻어오는 API는 한번만 호출하자!

Ti.Platform.xxxx 형태의 API는 비용이 비싸므로 반드시 로컬변수에 사용할 값을 캐시해서 사용한다.

var DEVICE_WIDTH = Ti.Platform.displayCaps.platformWidth;

3. 윈도우를 생성할 때 주의할 점.

윈도우는 비싼 비용을 지불하고 만드는 녀석이다. 특히 컨테이너로서 윈도우 안에 많은 뷰나 컨트롤들이 올라가게 되고, 이벤트를 바인딩 했다가 해제를 제대로 못하는 경우엔 메모리누수가 생길수가 있다. 따라서 습관적으로 윈도우가 닫힐때 $.destroy()를 실행시켜주자.

$.window.addEventListener("close", function(){
    // 특히, dataCollection 메소드를 이용해 데이터 바인딩을 한 경우 반드시 실행해야한다. 
    $.destroy();
});

4. 다중 윈도우를 이용해 뷰를 구성할때 주의할 점.

FaceBook과 같은 레이아웃을 구성할때는 가장 밑단에 깔리는 리스트 뷰는 매번 생성할 필요가 없다. 다만 쓰기나 상세 보기처럼 잠깐 나왔다가 사라지는 윈도우라면 매번 생성해되 윈도우가 닫힐때 걸린 핸들러를 잘 해제해준다. 위 3번 참고.

5. 이미지를 다룰때는 반드시 ImageView에 올리자.

캐시하는 방법은 Image_Best_Practices 문서를 참고한다.

6. 전역 이벤트 리스너를 윈도우와 혼합할때 생기는 메모리 누수

다음 코드처럼 동적으로 생성한 컨테이너를 전역 이벤트 리스너에서 사용한 경우 절대 지워지지 않는다! 주의하자!

var someFunction = function() { 
    var table = Ti.UI.createTableView(), 
        label = Ti.UI.createLabel(), 
        view = Ti.UI.createView();

    Ti.App.addEventListener('bad:move', function(e) {
        // table은 지역변수지만 앱이 종료되기 전까지 해제되지 않는다. 
        table.setData(e.data);
    });

    view.add(table);
    view.add(label);
    return view;
};

그밖에 ACS 이슈들..

1. ACS에서 있는 데이터를 fetch 할때 ORDER를 따로 지정하지 않으면, 랜덤하게 넘어오므로 ORDER를 지정하자.

2. ACS에 RESTful API는 구현되어 있으나 Ti.Cloud 객체에 구현되지 않는 객체도 있다.

3. 서버 이슈를 클라이언트로 끌어들이지 말자!

애플도 버린 1세대 아이패드 탈옥으로 새생명 불어넣기

벌써 3년전인가? 기억도 가물거린다. 여튼 애물단지 1세대 아이패드는 하드웨어가 너무 꾸져서 iOS6로 업그레이드도 안되는 구닥다리다. 이미 애플에서도 버린 자식이다.  64GB 되는 용량이지만 USB로 쓰기엔 너무 무겁다. -_-;; 그러다가 문득 토렌토만 받을수 있다면… 이라는 생각이 들어서 어제부터 씨름을 시작했다. 그리고 결국 해냈다.. ㅋㅋㅋ 자 그럼 지금부터 알아보자!

1. 탈옥하기

일단 탈옥을 해야한다. 완탈은 이미 너무나 쉽게 할수 있으므로 따로 설명안하겠다. 검색하면 나온다.

2. Cydia에서 필요한 소프트웨어 다운받기

이제 기본 소프트웨어를 설치하자. 다음 프로그램을 Cydia에서 다운받자.

  • Aptitude
  • Core Utilities
  • iFile
  • MobileTerminal
  • OpenSSH
  • Vi IMproved 추가로 위 소프트웨어를 깔았다면 MobileTerminal 이나 SSH접속을 통해서 아이패드 root 패스워드를 바꿔본다. 물론 안해도 상관없지만, 터미널 상에서 커맨드 입력을 나중에 해야하기 때문에 터미널에 익숙해질겸 미리 해두는 것이 좋다.

3. 토렌토 설치하기

맥용 소프트웨어 중에 유명한 토렌트 클라이언트가 있다. 바로 Transmission!! 이 녀석이 iOS 버전도 있었다! +_+_+ 바로 iTransmission! 다운로드는 역시 Cyida 에서 다운로드 받을수 있다. 다운로드 받을때는 CLI부터 설치하고 클래식 버전과 iTransmission 2를 차례로 설치한다. iTransmission 3도 있는데, 3는 iOS6용 인지 내 아이패드에선 안되는 건지 여튼 난 그냥 2 까지만 업그레이드 했다. 자 이제 아이패드 바탕화면에는 Terminal과 iFile 그리고 iTransmission 이 설치되어 있을것이다. 만약 아이콘 그냥 백지상태로 있다면 아이패드를 끄고 다시 부팅하면 제대로 된 아이콘으로 보인다.

4. 토렌토 파일 다운로드 하기

토렌토 파일을 다운로드 받으려면 별도의 사파리 플러그인이 필요하다. Cydia에서 Safari Download Plug-In을 설치한다. 그리고 웹서핑 후 토렌토 파일을 다운로드 하면 iTransmission으로 연결할수있을 것이다. 가끔 토렌토 파일이 다운로드 되지 않는 경우가 있을텐데.. 이럴땐 PC에서 다운로드 받아 Transmission으로 연다음에 magnet 주소를 복사해서 iTransmission에 붙여넣으면 된다.

5. ipa 파일 설치하기

NPlayer이나 AVPlayer는 모두 유료 어플이지만 탈옥을 했다면 이런 유료 어플도 손쉽게 ipa를 구해서 설치할수가 있다. 일단 모바일 사파리의 경우 ipa 파일이 다운로드가 되지 않으므로 안드로이드폰이나 PC에서 해당 ipa 파일을 다운로드 받은 다음 아이패드로 옮긴다. 아이패드로 옮기는 방법은 여러가지가 있지만 나는 Dropbox 공유를 통해서 아이패드로 다운로드 받았다. 아이패드로 파일을 옮겼다면 이것을 다시 설치해야한다. 일단 설치하기 쉽도록 터미널의 기본 위치인 /var/mobile 폴더로 옮겨놓자. 옮기는 방법은 iFile에서 옮겨도 되고, 터미널 상에서 mv 명령어를 이용해도 된다. 이제 ipa 파일 설치를 위한 프로그램을 깔아보자. cydia에서 IPA Installer Console 을 설치하자. 설치한 후에는 터미널에서 #> ipainstaller 파일이름.ipa 를 입력하면 설치가 된다.  

6. 별도 cydia 소스 파일

탈옥할 경우 기본으로 포함된 패키지 저장소 소스파일이 있는데 혹시나 없을 경우에는 추가하면 된다.

  • http://apt.thebigboss.org/repofiles/cydia/
  • http://apt.saurik.com/
  • http://repo.insanelyi.com/
  • http://apt.modmyi.com/
  • http://cydia.xsellize.com/
  • http://cydia.zodttd.com/repo/cydia