몇일전 2011 Adobe Community Professional(ACP)이 되었다는 메일을 받았습니다. 


ACP는 전세계적으로 300명내외 있습니다. 한국에는 저를 비롯해 열이아빠로 잘알려진 이준하님, Flex 엔터프라이즈 컨설팅으로 활동중이신 배준균님, 작년 소셜게임 최고의 주가를 달렸던 선데이토즈 대표 이정웅님, ActionScript 카페를 운영하며 지속적인 활동중이신 땡굴이 강성규님, 총 5명이 2011 ACP가 되었습니다. 

작년에는 이렇다할 활동을 못해 아쉬웠는데, 올해는 새로운 팀블로그 파워플(http://powerfl.com) 을 통해 꾸준한 글을 올리고 개인블로그를 통해 지속적인 관련 기술을 공유하려고 합니다. Flash에 대해 일주일에는 한개 이상 올리는 것을 목표로 삼으려고 합니다. 오프라인 활동은 회사에서 제 위치 때문에 많이 못합니다. 대신 온라인 활동을 주로 하려고 합니다. 

열심히 활동하겠습니다.


개인적으로 ActionScript 3.0 기반에서 개발을 많이 하다보니 Objective-C의 target/selector 형태로 접근하는게 익숙하지 않았다. 사실 ActionScript 3.0에서는 더 고수준으로 랩핑 처리하다 보니 selector격인 함수의 참조만 보내줘도 되긴하다. 그렇지만 이러한 사실이 이해가 된다고 하더라도 매번 target/selector를 보내고 처리하는게 여간 불편하지 않았다.

아래는 Objective-C에서 target/selector를 사용하는 방법이다. 뭔가 다른 클래스에 대리 요청을 하기 위한 방법으로 이렇게 많이 쓸 것이다.

위 방법이 익숙해지면 사용하는데 어렵지는 않다. 그냥 target/selector 넘겨주고 실행해주면 그만이다. 앞서 말했지만 나는 이러한 것에 익숙하지 않다. 그래서 2개를 보내는 형태가 아닌 하나로 묶어서 보내고 싶었다. 아래처럼 말이다. 


위 도식에서 Action클래스는 target/selector를 관리하고 실행해주는 역할을 한다.

뭔가 더 복잡해보인다. 하지만 이 방법의 장점은 target/selector로 두개의 변수를 관리하는게 아니라 이것을 하나로 묶은 Action클래스의 객체만 관리하면 된다는 것이다. 

Action내에 있는 target/selector를 실행하기 위해 위 도식에서 [_tempSuccessAction run]과 같이 하면 된다. 이것을 조금더 확장해서 생각하면 [_tempSuccess runWithData:data] 처럼 할 수 있고 스레드에도 대응시키기 위해 [_tempSuccess runInThreadWithWaitUntilDone:YES] 와 [_tempSuccess runInThreadWithData:data waitUntilDone:YES] 처럼 사용할 수 있도록 Action에 관련 메서드를 추가해도 된다. 이렇게 생각해보니 Action 클래스로 target/selector를 관리하는게 여러가지로 장점이 될 수 있다는 것을 알 수 있다. 

아래 코드는 Action 클래스의 header 정의 부분이다.

//

//  Action.h

//

//  Created by Yongho Ji on 10. 12. 7..

//  Copyright 2010 Wecon Communications. All rights reserved.

//


#import <Foundation/Foundation.h>


//target/selector 하나로 묶고 실행해주는 클래스 

@interface Action : NSObject 

{

@private

id _target; //selector 가지고 있는 클래스 객체 참조

SEL _selector; //target안에 정의된 selector 메서드 

}


//초기화 

-(id)initWithTarget:(id)target selector:(SEL)selector;


//target/selector 실행 

-(void)run;


//target/selector 실행하되 selector인자로 data 넘김 

-(void)runWithData:(id)data;


//(Thread안에서 호출)target/selector 실행.

-(void)runInThreadWithWaitUntilDone:(BOOL)waitUntilDone;


//(Thread안에서 호출)target/selector 실행하되 selector인자로 data 넘김 

-(void)runInThreadWithData:(id)data waitUntilDone:(BOOL)waitUntilDone;

@end



Thread내에서는 runInThread... 를 호출해주면 그만이다. 구현부를 보자.

//

//  Action.m

//

//  Created by Yongho Ji on 10. 12. 7..

//  Copyright 2010 Wecon Communications. All rights reserved.

//


#import "Action.h"



@implementation Action


-(void)dealloc 

{

[super dealloc];

//[_target release];

}


-(id)initWithTarget:(id)target selector:(SEL)selector 

{

if (self = [super init]) 

{

//[target retain];

//[_target release];

_target = target; //retain하지 않고 assign 한다. 왜냐하면 retain하면 메모리 누수를 야기시킬 있으므로 

_selector = selector;

}

return self;

}


-(void)run 

{

@try {

if (_target != nil && _selector != nil

{

[_target performSelector:_selector];

}

}

@catch (NSException * e) {

NSLog(@"%@",e);

}

}


-(void)runWithData:(id)data 

{

@try {

if (_target != nil && _selector != nil

{

@try {

[_target performSelector:_selector withObject:data];

}

@catch (NSException * e) {

[_target performSelector:_selector];

}

}

}

@catch (NSException * e) {

NSLog(@"%@",e);

}

}


-(void)runInThreadWithWaitUntilDone:(BOOL)waitUntilDone 

{

@try {

if (_target != nil && _selector != nil

{

[_target performSelectorOnMainThread:_selector withObject:nil waitUntilDone:waitUntilDone];

}

}

@catch (NSException * e) {

NSLog(@"%@",e);

}

}


-(void)runInThreadWithData:(id)data waitUntilDone:(BOOL)waitUntilDone

{

@try {

if (_target != nil && _selector != nil

{

@try {

[_target performSelectorOnMainThread:_selector withObject:data waitUntilDone:waitUntilDone];

}

@catch (NSException * e) {

[_target performSelectorOnMainThread:_selector withObject:nil waitUntilDone:waitUntilDone];

}

}

}

@catch (NSException * e) {

NSLog(@"%@",e);

}

}



@end



사용방법은 이미 설명했다. 간단한 아이디어지만 좀 더 확장해서 생각해보면 Action 클래스에 추가할 수 있는 것들이 많을 것 같다.


비슷한 이유에서 통지대신 이벤트를 만들어 사용한다.
NSNotification 대신 Event 사용하기 http://blog.jidolstar.com/721

글쓴이 : 지돌스타(http://blog.jidolstar.com/742




스타플에서 타임라인을 새롭게 개편해서 베타 오픈을 했습니다. 미진한 점이 아직 많으나 사용자들의 의견을 듣고자 베타로 오픈합니다.


스타플 타임라인 : http://timeline.starpl.com (PC에서만 접속하실 수 있습니다.)
(샘플1)위콘의 타임라인 : http://timeline.starpl.com/wecon
(샘플2)지돌스타의 타임라인 : http://timeline.starpl.com/jidolstar


기존 타임라인은 스타플 서비스 자체에 포함되어 있는 형태였습니다. 수차례에 걸쳐서 타임라인을 전면 개편하면서 지속적인 사용성을 높혀왔습니다.

스타플 최초 타임라인 - 길다란 달력형태


2번째 스타플 타임라인 - 카테고리와 글로 엮어짐

3번째 스타플 타임라인 - 키워드로 엮어짐

4번째 스타플 타임라인 - 중요기록과 키워드로 묶음


스타플을 최근에 사용하셨던 분들은 정말 놀라셨을지도 모르겠네요. 이런 역사가 있었다니 말이죠? ^^

기존 사용자분들은 스타플이 지난해 말에 개편하면서 타임라인이 없어진 것에 대해 많이들 아쉬워 하셨습니다. 제작하는 우리도 너무 아쉬웠으나 스타플을 더욱 유용하고 좋은 서비스로 탈바꿈하기 위한 선택이였음을 이해해 주실 것이라 생각합니다.

관심사로만 묶여서 자신의 공간을 잃어버린 것 같다는 아쉬움을 이제 타임라인을 통해 찾으실 수 있게 되었습니다.

타임라인은 기존 스타플과 연동이 됩니다. 즉, 타임라인에서 작성하신 글은 스타플에도 올라갑니다. 반대로 스타플에 올리신 글은 타임라인으로 보낼 수도 있습니다.


스타플 회원이시라면 누구나 http://timeline.starpl.com 으로 접속하시면 스타플 타임라인을 사용하실 수 있습니다. (모바일 사용자는 PC를 통해 접근하셔야 합니다.)


처음 접속하시면 위와 같은 문구를 보실 수 있습니다. 베타 버전은 기존 타임라인 사용자의 글이 올라와 있지는 않습니다. 대신 정식 오픈때에 복구 서비스를 진행할 예정입니다. 타임라인에 대한 문의 및 의견은 스타플에서 <타임라인> 관심사를 넣어주시고 글을 작성해주시면 됩니다. http://starpl.com/jidolstar/keyword/10078175/space 처럼요.   



타임라인 처음 접속했을대 모습입니다. 아무것도 없지요. 여러분은 어렵지 않게 타임라인에 직접 글을 작성하시거나 스타플에 작성된 글을 타임라인에 담으실 수도 있습니다.



타임라인 추가나 편집하기를 통해 타임라인에 카테고리를 넣으실 수 있습니다.


위 화면은 스타플에서 올린 글을 타임라인에 가져오는 기능입니다. 만들어진 카테고리에 자신만의 추억을 담아보세요.



타임라인에 스타플에 올렸던 제 글들을 올려봤습니다. 이제 좀 그럴듯해지네요.



타임라인은 스킨도 지원합니다. 전 개인적으로 이 색이 가장 좋네요.




배경에 이미지도 입힐 수 있어요. 아직 사용자가 직접 올리는 기능은 없지만 조만간 지원해주지 않을까요? ^^;





타임라인에 올린 글이나 사진은 위처럼 보실 수 있어요. 양쪽에 방향버튼 (< , >)를 클릭하시면 이전, 이후 사진을 보실 수 있고요.


스타플에도 작은 변화가 생겼습니다.


스타플에 블랙홀 같은 별이 아래 처럼 바뀌었어요. 옆에 타임라인 행성도 보이네요.


타임라인 행성을 선택하시면 바로 타임라인으로 이동합니다. 가운데에 나의 별을 선택하시면 아래와 같은 멋진 화면도 보실 수 있죠. 마우스 드래그로 하면 회전도 되고 마우스 스크롤로 확대축소할 수 있습니다. 별똥별도 떨어지네요 ㅎ




물음표(?)는 다음 서비스를 말하는 것이겠죠? ^^ 무엇일까요? 저도 아직 모릅니다. 아무튼 더 좋은 서비스를 만들게 되면 내별에 또 다른 행성이 붙게 되겠네요.


스타플에서도 타임라인에 직접 글을 올릴 수 있습니다. 자신의 글의 '수정|삭제' 옆에 시계모양의 '등록' 버튼을 이용하시면 됩니다. 모바일 회원이 작성하신 글은 모바일 아이콘이 표시됩니다. 타임라인에 작성된 글은 타임라인 표시가 주어집니다.




스타플 타임라인에 대해서 간략히 소개했습니다.

말씀드렸지만 아직 베타라 중간중간 버그도 있고 사용성도 미진한 부분이 있습니다. 좋은 아이디어나 개선사항 있으시면 언제든지 '타임라인'관심사로 글을 작성해주세요. 성심성의껏 의견을 참고해서 반영할 수 있도록 노력하겠습니다.

스타플 타임라인에 여러분의 추억을 담아보세요.

http://timeline.starpl.com (모바일은 지원을 하지 않고 있습니다. PC를 이용해 주세요.)

글쓴이 : 지돌스타(http://blog.jidolstar.com)




2011년에 들어서 재미있는 사이트가 생겨났다. ActionScript 3.0 코드기반 SNS인 Wonderfl.net에서 만들어진 사이트로, 이 사이트를 통해 wonderfl에서 만들어지는 Flash 컨텐츠를 웹상에서 안드로이드 apk로 자동으로 변환해 다운로드 받을 수 있다.

Flash2Android : http://wonderfl.net/flash2android

단, 이 서비스는 2011년 1월 말까지만 할 예정인 것 같다. 그 이후는 어떻게 될지 잘 모르겠다.

위 사이트를 어떻게 활용할 수 있는지 궁금해하는 사람을 위해 짧은 동영상을 준비해 보았다.


 
코드 경로 : http://wonderfl.net/c/zPyr

위 동영상에서 보여주고 있는 과정을 성공적으로 수행하기 위해 아래 내용을 알고 있어야 하겠다.
1. 안드로이드 OS가 2.2 프로요 이상이어야 한다.
2. 안드로이드 폰에 Adobe AIR가 설치되어 있지 않는다면 중간에 설치과정이 필요하다.
3. 안드로이드 폰에서 설정 > 응용프로그램 > 알 수 없는 소스(시판되지 않은 응용프로그램 설치 허용)이 체크되어 있어야 한다.
4. wonderfl.net에서 Flash 컨텐츠를 apk로 변환할 수 있는 것은 자신이 직접 Fork(일종의 펌질)나 작성된 코드에 국한된다.

wonderfl.net에서 ActionScript 3.0이나 Flex 코드를 웹사이트를 통해 컴파일 할 수 있던 것은 Adobe에서 관련 컴파일러를 공개하기 때문에 가능하다. 안드로이드 컴파일러도 공개가 되어 있기 때문에 이 모든것이 가능한 것이라 생각하면 되겠다.

모든 Flash 어플은 모두 안드로이드 APK로 변환될 수 있다. 하지만 모두 정상동작하는 것은 아니다. 데스크톱 브라우져에서 돌아가는 플래시 중에는 키보드 입력으로 동작하는 것들이 꽤 있다. 이러한 것들은 안드로이드 폰에 설치한 후 실행이 된다 하더라도 동작을 시킬 수 없다. 또한 마우스 이벤트와 터치는 엄연히 다르며모바일은 제약된 사양을 가지므로 데스크탑만큼 좋은 퍼포먼스를 보여줄 수 없기 때문에 이에 대한 최적화 과정도 반드시 필요하다. 

wonderfl에서 작성했던 플래시 어플중 키보드로 동작되던 것을 터치이벤트 또는 가속센싱 이벤트를 통해 동작하도록 바꾼뒤 테스트를 해보았다.

아래 동영상은 ABC flyer라는 일본의 개발자가 올린 플래시 어플이다. 이 어플을 Fork한뒤 키보드 대신 가속도 센싱을 이용해 비행기를 조정하도록 수정해 보았다.


 
작성 코드 : http://wonderfl.net/c/eTHE

Flash Player 10.1, AIR 2.0 부터는 가속계를 사용할 수 있는 API인 flash.sensors.Accelermeter가 추가 되었기 때문에 이것이 가능한 것이다.

다음 동영상은 예전에 키보드 이벤트를 이용해 2D 상에서 비행기를 부드럽게 움직이는 방법을 모색하기 위해 만들었던 플래시 어플이다. 키보드 대신 멀티터치 이벤트를 이용해 적용해보았다.


 
멀티터치 적용전(키보드) 코드 : http://wonderfl.net/c/57qJ
멀티터치 적용후 코드  : http://goo.gl/x0KAW

Flash CS5 및 Flash Builder Burrito 에서 위 코드는 모두 테스트 해볼 수 있다.


정리하며
Flash가 장점인 것은 hika님의 말대로 배포라는 것에 동의한다. 설계, 기획, 제작과정을 보자면 C, C++, Java와 같은 보편적으로 널리 사용되는 언어로 개발하는 것과 비교할때 쉽다고 생각할 수 있지만 VM이라는 제약환경때문에 퍼포먼스를 올리기 위한 노력에 비하자면 오히려 더 어려운 경우도 발생한다. 하지만 배포만큼은 Flash를 따라올 수 있는 플랫폼이 아직 존재하지 않는다.

이 배포는 종전까지 웹과 데스크탑(AIR)로 국한되었지만 이제 다양한 디바이스들도 이에 포함되게 되었다. 이 글의 내용이 그러하듯이 말이다. 그렇다고 개발이 편해지는 것은 아니다. 지금까지 쌓아왔던 노력과 리소스는 분명 활용될 수 있지만 디바이스 마다 특색이 있어 접근 방법이 다르기 때문에 그에 대한 개발 비용은 여전히 존재한다. 

Flash는 앞으로 크로스 플랫폼 지원과 더불어 3D는 행보도 볼만할 것 같다. 차세대 Flash Player의 코드명 Molehill은 그 가능성을 보여주었다.

앞으로 Flash의 행보가 어떻게 될지 기대가 된다.


참고글
Flash2Android : http://wonderfl.net/flash2android
Flex로 쉽게 모바일 어플을 만들자. - Adobe AIR Launchpad : http://blog.jidolstar.com/717
원더플(Wonderfl)을 이용해 ActionScript 3.0을 공부하자. - 자동 테스트 환경 구축 소개 : http://blog.jidolstar.com/669
플래시 빌더 5 프리뷰 설치해보기 : http://koko8829.tistory.com/934
안드로이드 2.2 프로요와 Flash Player 10.1의 만남 : http://blog.jidolstar.com/712
어도비, 모바일과 다양한 기기를 위한 에어 2.5 공개 : http://blog.jidolstar.com/716
차세대 Flash Player 3D API Molehill : http://blog.jidolstar.com/733
Flex Test Drive for Mobile - Build a mobile application in an hour : http://goo.gl/qm8PY
What's new in Flash Builder "Burrito" : http://goo.gl/Z4Baz
Introducing Adobe Flex SDK "Hero" : http://goo.gl/dYzbH
Mobile development using Adobe Flex SDK "Hero" and Flash Builder "Burrito" : http://goo.gl/5iiZM
Coding productivity enhancements in Flash Builder "Burrito" : http://goo.gl/bSb4r

글쓴이 : 지돌스타(http://blog.jidolstar.com/739)

스타플에서 '작심삼일' 아이폰/아이팟터치 어플을 배포합니다. 

작심삼일 어플은 '영어공부', '금연하기', '애인만들기', '다이어트', '부자되기', '책읽기'등 신년에 들어서 하고 꼭 하고 싶지만 실천하기 어려운 계획을 실천할 수 있도록 도와주는 것을 목적으로 삼습니다.

또한 각 계획별로 같은 목표를 삼은 사람들과 함께 각자의 고민을 공유하고 실천할 수 있도록 도움을 줄 수 있게 커뮤니티를 지원합니다.

계획을 잘 실천하고 있는지 매일 체크할 수 있는 체크캘린더 기능도 포함하고 있습니다.

그리고 계획시작 3일간 실천의 도움을 주고자 알림서비스를 제공합니다.

스타플에서는 "올해는 꼭 성공하자! 나의 신년계획!" 이벤트를 진행중입니다.

이벤트 페이지 : http://starpl.com/main/event/view/68



시작이 반이라고 합니다. 작심사일 어플을 통해 여러분의 계획을 꼭 실천에 옮겨보세요. ^^


앱스토어 : http://goo.gl/mkGZA
앱스토어 QR 코드 :

스크린 샷입니다.








글쓴이 : 지돌스타(http://blog.jidolstar.com)
iOS 어플상에서 기기의 종류를 알아올 수 있는 코드이다.

#include <sys/sysctl.h>    // sysctlbyname 의 사용을 위해

// 모델 정보 보기 - 상세히
+ (NSString *) platform {
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    /*
     Possible values:
     "i386" = iPhone Simulator
     "iPhone1,1" = iPhone 1G
     "iPhone1,2" = iPhone 3G
     "iPhone2,1" = iPhone 3GS
     "iPhone3,1" = iPhone 4
     "iPod1,1"   = iPod touch 1G
     "iPod2,1"   = iPod touch 2G
     "iPod3,1"   = iPod touch 3G
     */
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    
    return platform;
}

출처 : http://cafe.naver.com/mcbugi/81305



몇 일전 저는 뜻하지 않게 감동적인 선물을 받았습니다. "마로의 꿈 - 액션스크립트 3.0으로 배우는 소셜 게임 프로그래밍" 이라는 이명희/김종훈 님이 쓰신 책이였습니다.

몇 번 책선물을 받은 적이 있지만 이번 책은 너무도 특별했습니다. 바로 저자인 이명희님께서 직접 엽서까지 보내서 선물로 주신 겁니다. 사실 이명희님를 만난 적이 없는 것 같습니다.(제가 오프라인 활동을 너무 안하다 보니...) 이명희님께서는 원래 C/C++ , Java등 다른 분야에서 개발하시던 분인데 게임 개발을 위해 ActionScript 3.0을 접하시다가 제 블로그를 알게 되었다고 합니다. 책을 보낸 이유는 제 블로그를 통해 도움을 많이 받아 감사하다는 것이였습니다. 초판 날짜를 보니 아마도 발행되자마자 바로 보내셨더군요. 정말 감동이였습니다.

처음에는 다 그렇듯이 Flash 개발이 쉽다고들 하지만 그것은 어디까지나 Flash IDE를 통해 디자인적 접근이 그러한 것이고 게임처럼 고도의 경험과 기술이 들어가는 분야로 접근하면 다른 언어와 마찬가지로 어려운 것은 사실입니다. 왜냐하면 Flash 게임개발은 그 분야대로 노하우가 필요한 것은 분명하니깐요. 아마도 diebuster(http://diebuster.com)을 방문해서 글을 보신 경험이 있다면 Flash가 결코 만만하지는 않구나라는 생각이 들겁니다. Flash가 대중적이긴하나 VM이기 때문에 속도와 질을 극대화 시키는 것은 쉽지 않거든요. 특히나 게임분야는 말할 것도 없지요.

책 소개를 해야겠네요. 이 책은 "마로의 꿈"이라는 게임을 기반으로 쓰여진 책입니다. 저자가 직접 간단한 소셜게임을 만들었고 그 게임에 녹아있는 각종 스킬을 소개하는 내용을 담았습니다. 마지막에는 게임에 사용된 인공지능 및 소셜게임을 네이버에 등록하는 방법도 소개합니다. 게임은 2D지만 여느 소셜게임처럼 3D 느낌을 다룹니다. 자원생성, 자원관리, 지도제작, 아바타 제작 및 애니메이션등 정말 소셜게임이 필요한 핵심내용을 담고 있습니다. 게임이라는 특성상 진부하고 어려운 내용을 담을 것 같지만 실제로 이 책은 300페이지가 채안되면서도 간단하고 명쾌하게 설명해주고 있어서 처음 소셜게임에 입문하시는 분들에게는 국내서적으로 이만한 책은 없다고 생각합니다.

국내에서 IT서적하면 항상 인기부류인 기초를 다루는 책이 나오는 것이 실상임에도 이런 책이 출판이 될 수 있었다는 것도 참 신기합니다. 요즘 스마트폰 붐으로 약간 침체된듯한 국내 Flash분야에 활기를 불어넣는데 이 책이 일조할 수 있을 것이라 생각합니다.

글쓴이 : 지돌스타(http://blog.jidolstar.com/736)

Objective-C에서 retain/release 메커니즘을 이해하고 익숙해지는데 오랜 시간이 걸렸다. 이해 자체는 빠를지언정 적절히 쓰는 건 많이 어려운 것 같다.

retain/release/autorelease 를 쓰는 이유는 사실 많이 공개되어 있다. 하지만 retain을 하면 안되는 경우에 대해 다루는 글이 많지 않은 것 같다.

delegate는 기본적으로 retain이 아닌 assign을 한다. 만약 ViewController가 어떤 객체의 delegate대상으로 설정될때 retain을 해버리면 어떤 객체가 delegate를 release해주지 않는 이상 ViewController는 dealloc이 호출되지 않는 문제가 발생한다. 그러면 자연스럽게 메모리 릭(memory leak)이 발생한다. 그렇기 때문에 delegate는 assign을 해주는 것이다.

이런 경우도 있다. UITableViewCell을 커스터마이징처리한 CustomTableViewCell이 있다고 하자. 여기에 UITableViewController를 확장한 MyTableViewController가 이 CustomTableViewCell을 사용한다고 가정하자. 보통 같으면 사용에 문제가 없지만 만약 CustomTableViewCell에서 MyTableViewCeontroller의 메서드를 호출할 수 있게 하기 위해 MyTableViewController 객체 자신(self)과 그 메서드(@selector(myMethod:))로 CustomTableViewCell에서 참조하게 할 수 있다. 이때 MyTableViewController의 참조를 retain해줘버리면 나중에 MyTableViewController이 dealloc 메서드가 호출될 시점을 읽어버릴 가능성이 100%가 된다. 왜냐하면 CustomTableViewCell에서 retain처리된 MyTableViewController의 객체를 다시 release할 수 있는 명확한 메커니즘을 추가하기 힘들기 때문이다. 그래서 이런 경우에도 retain이 아닌 assign을 사용함이 옳다.

조금 다르지만 NSTimer를 이용할때도 비슷한 경험을 할 수 있다. [NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:] 메서드를 통해 target과 selector를 넘겨주는데 이때 내부적으로 NSTimer는 자기 자신과 target을 retain시켜주는 것 같다. 그래서 [timer invalidate] 호출해주지 않으면 target의 dealloc이 절대 호출되지 않는다. 역시 이 경우에도 메모리 릭이 발생한다. 그러므로  NSTimer를 시작하고 나서 멈추는 시점은 dealloc 내에서 하면 안되며 UIViewController의 경우 viewWillDisappear나 viewDidDisappear와 같은 메서드에서 invalidate를 호출해줘서 정상적으로 UIViewController의 객체의 dealloc 메소드가 호출되도록 해주어야 한다.

이외에도 굉장히 많은 경우도 메모리 릭은 항상 존재할 수 있다. 그래서 보통 일반적으로 통용되는 규칙을 잘알고 그대로 하는 것이 좋고 그렇게 하는 이유도 이해하면 크게 도움된다.

결국 위의 예제는 여기서 제공해주는 일종의 팁정도로만 생각하고 요점은 항상 dealloc 메서드가 호출되는지 확인하는 자세가 필요하다. 그렇게 되면 최소한 메모리 릭이 발생되는 최초 근본원인은 찾아낼 수 있을 것이다. 

종류가 다른 하나의 팁으로 정확한 원인은 모르겠지만 NSZombieEnabled를 사용 하면 EXC_BAD_ACCESS가 발생하지 않는데, 그것만 없애면  EXC_BAD_ACCESS가 발생하는 경우에는 dealloc 부분에서 디버깅을 해보면 어떤 객체에서 문제가 발생하는지 찾을 수 있다. 이 에러는 보통 과도한 release를 하는 경우 발생하는 것인데, 아무리 봐도 문제점을 찾을 수 없는 경우였다. 이런 경우 dealloc 메서드 내에 [super dealloc]를 실행문의 맨 뒤에 호출하도록 하면 문제가 없어지기도 한다.

그림이나 코드없이 말로만 줄줄 써서 이해가 잘 안갈 수도 있다. 결국 중요한 것은 dealloc이 제대로 호출되는지 항상 체크하라는게 여기서 말하고 싶은것이다.

글쓴이 : 지돌스타(http://blog.jidolstar.com/735)

Flash Player 10.2 beta가 2010년 12월 초에 배포가 되었다. 아무튼 강력한 GPU가속을 이용해 비디오 렌더링을 최적화 시킨 것이 가장 큰 변화라고 볼 수 있겠다. GPU를 이용하다보니 CPU 사용율이 급격히 줄어든다. 아래 동영상을 통해 Flash Player 10.2 beta의 GPU를 이용한 동영상 렌더링 효과를 눈으로 확인할 수 있다.


현재 Flash Player 10.2 beta는 정식 버전이 아니므로 자동으로 배포되어지지 않는다. 그러므로 다음 링크를 통해 다운로드 받을 수 있다. 개발자라면 debug 버전을 받을 것을 추천한다.


이번 배포의 변화는 다음과 같다.
1. Stage Video 하드웨어 가속
2. IE9에서 하드웨어 가속 지원
3. 네이티브 커스텀 마우스 커서 지원
4. 멀티모니터에서 풀스크린모드 지원 

이미 꽤 지난 내용이라 검색해보면 한글로된 설명글들도 있다.


Flash 분야에 손놓고 지낸지 오래라... 좀 파악하고 있는 중이다. ㅎㅎ

글쓴이 : 지돌스타(http://blog.jidolstar.com) 

지난 Adobe MAX 2010에서 가장 이슈가 되었던 것중에 하나가 GPU 가속을 상시 지원해줄 수 있는 Molehill이라는 Flash Player 3D API 가 아닌가 싶다. Molehill은 Flash Player 3D APIs의 코드네임이다.

지금까지 Flash Player가 일부 GPU 가속을 지원해줬기 때문에 테스트 정도로만 가능했지만, 미래에 GPU를 상시 지원하게 되는 Molehill 3D API가 차세대 Flash Player에 장착하게 되면 파급효과가 클 것으로 생각된다. 

CPU에 의존해 왔던 3D 기존 프레임워크인 Away3D나 Alternativa3D등은 Molehill로 변환되어 배포될 것이고 많은 Flash 컨텐츠 제작사, 소셜게임제작사들이 새로운 Flash Player 3D API를 이용한 다양한 어플들을 내놓을 것이다. 더불어 이들 어플들은 고스란히 모바일에도 접목되게 될 것으로 예상이되어 파급효과가 클 것으로 전망이 된다.

지속적으로 Molehill에 대해서 관심을 가지고 지켜볼 필요가 있겠다.



위에 두 영상화면을 보고 Flash Player 에서 동작하는 모습이다라면 누가 믿겠는가? ㅎㅎ

읽을만한 글
Adobe Labs - 3D APIs for Adobe Flash Player and Adobe AIR
Adobe MAX 2010에서 소개된 차세대 GPU 가속 Flash API - Molehill
Molehill Flash Player 3D APIs 소개
Flash Player 3D APIs 간단한 소개글 - 잼있음
[동영상][at MAX 2010] GPU Acceleration on Adobe AIR "Molehill" - 우야꼬 군이 직접 미국에 MAX 행사에가서 찍은 영상입니다.
[동영상][at MAX 2010] Alternativa 3D in Adobe MAX 2010 - 우야꼬 군이 직접 미국에서 Molehill을 체험했군요.
[동영상] Adobe MAX 2010 - Alternativa 3D 시연 - 땡굴이 님께서 Alternativa의 시연모습을 동영상으로 담았습니다.
Molehill Programming Tutorial
ActionScript의 언어 순위는 몇 위일까?

글쓴이 : 지돌스타(http://blog.jidolstar.com/733)

아이폰 어플을 개발하다보면 현재 인터넷 접속이 가능한지 확인해야할 필요가 있다. 또 사용성 측면에 있어서도 네트워크가 연결되어 있는 상태인지 확인해서 인터넷 사용이 가능한지 메시지를 보여주는 일도 중요할 수 있다. 또 어떠한 경우에는 3G인지 WiFi인지 알 필요가 있을 수 있다.

 

이러한 일을 위해 직접 만드는 것도 좋지만, 빠르게 어플을 개발해야하는 입장에서는 그것마저 부담스럽니다. 

그러므로 검색이 필요하다. 

 

검색해보니깐 아주 유용한 소스를 발견했다. 바로 Reachability 이다. 

애플 예제소스로 공개된 것이다.

 

http://developer.apple.com/iphone/library/samplecode/Reachability/Introduction/Intro.html

 

위에서 제공하는 소스를 다운로드 받아 X-code에서 직접 실행해보자. 네트워크 상태를 껐다가 켰다가 하면서 실험해보자. 잘 동작한다. 아래는 본인이 직접 시뮬레이터 상에서 동작시켜본 것이다. 

 

 


사용법은 단순하다.

1. Reachability.h와 Reachability.m을 자신의 프로젝트의 클래스로 등록한다.

2. SystemConfiguration.framework 프레임워크를 추가시킨다. 

3. 사용한다. ^^

 

가령 현재 상태가 WiFi인지 WWAN(3G)인지 확인하려면 아래처럼 코딩을 하면 되겠다.


 


실시간으로 네트워크 상태변화를 감지하고 싶다면 Notification기능을 활용하면 된다. 이미 샘플코드에 다 정리가 되어 있지만 간단하게 설명하자면... 

 

먼저 아래와 같은 코드를 application:didFinishLaunchingWithOptions:와 같은 함수등에 넣는다. 여기서 _internetReach 변수는 Reachability *_internetReach;로 클래스 변수로 정의해둔다. 또한 dealloc시에는 [_internetReach release];_internetReach=nil;로 메모리 해제를 해주어야 한다.


 

그리고 다음과 같은 2개의 함수를 넣어서 간단하게 감지할 수 있도록 만들면 된다. 


 


이것으로 인터넷 연결상태를 실시간으로 감지할 수 있게 된다. 

 

개발자에 따라서 특정한 웹서버에 접속이 원할한지 확인할 필요가 있을지 모른다.

그러한 경우에는 샘플코드를 보면 아래와 같은 방법으로 사용했다. 

 

[[Reachability reachabilityWithHostName: @"www.apple.com"] retain];


이외에 샘플코드에 Local WiFi 감지를 하는 부분이 있는데, 사실 무슨의미인지는 잘 모를뿐더러 어디서 보니깐 실제 인터넷 접속감지는 위에서 소개한 2가지 방법만 사용해도 문제가 없는 것 같다.

 

동영상 강좌도 있다.

http://answers.oreilly.com/topic/1218-how-to-check-the-status-of-the-network-connection-from-your-iphone-app/

 

아주 간단하게 만들어진 소스도 있다.

http://theeye.pe.kr/entry/how-to-check-network-connection-on-iphone-sdk


글쓴이 : 지돌스타(http://blog.jidolstar.com/731)

아래와 같은 에러를 만나 본적이 있으신가요?


-[CALayer release]: message sent to deallocated instance


개발자가 만든 코드가 아니라서 디버깅해서는 찾기 힘든 경우입니다. 이런 경우에는 일단 예상되는 부분을 주석처리 해서 저 메시지가 안나오게 한다음 문제되는 부분을 분석해서 찾는 것이 속이 편한듯 싶습니다. 아니면 꼼꼼히 코드를 보면서 누수부분을 찾아야겠지요. 아직 Objective-C가 익숙하지 않아서 인지 찾는데 좀 시간이 걸리더군요.


제가 저 에러를 만났을때 문제가 되었던 것은 바로 적절한 retain을 해주지 않아서 였습니다.


//1 에러발생 : -[CALayer release]: message sent to deallocated instance

//단, dealloc에서 [_btnGlobal release];_btnGlobal=nil;을 호출해준다.

_btnGlobal = [UIButton buttonWithType:UIButtonTypeCustom];

[self addSubview:_btnGlobal];


//2 문제없음

//단, dealloc에서 [_btnGlobal release];_btnGlobal=nil;을 호출해준다.

_btnGlobal = [UIButton buttonWithType:UIButtonTypeCustom];

[_btnGlobal retain];

[self addSubview:_btnGlobal];


//3 문제없음

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

[self addSubview:button];


//4 문제있음 : Stack Over가 생김 

UIButton *button = [[UIButton buttonWithType:UIButtonTypeCustom]autorelease];

[self addSubview:button];


//5 문제있음 : 4번과 현상 같음 

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];

[self addSubview:button];

[button release];

//6 문제없음

UIButton *button = [[UIButton alloc]init];

[self addSubview:button];

[button release];

//7 문제없음

UIButton *button = [[[UIButton alloc]init]autorelease];

[self addSubview:button];

//8 메모리 leak발생

UIButton *button = [[UIButton alloc]init];

[self addSubview:button];


기본적으로 objective-c에서는 retain수와 release 수가 항상 같아야 메모리 문제가 발생하지 않지요. retain수>release수 가 되면 메모리 leak가 발생하고 반대로 retain수 < release 수가 되면 중간에 뻗어 버립니다. 그래서 오히려 전자가 더 찾기 힘들죠.


저한테 닥친 문제는 1번의 경우였습니다. 일단 _btnGlobal은 전역변수입니다. 여기에 @property, @synthesize와 같은 설정은 안했습니다. 그리고 dealloc함수에서 release시키죠. 1번에서 문제는 객체 생성시 new, init, alloc을 사용하면 기본적으로 autorelease되지 않아서 수동으로 release해야하며 반대로 new,init,alloc으로 생성하지 않는 경우에는 autorelease처리되어 release를 하지 않아도 된다는 점을 간과했습니다.  1번의 경우는 자동으로 release되었으니 처음에는 문제없이 동작하지만 dealloc함수가 호출시에 [_btnGlobal release]를 호출하기 때문에 release를 한번더 한 경우가 되어 에러를 발생시킵니다.  


그래서 1번 문제는 2번처럼 해주면 문제가 발생하지 않습니다. 


3번의 경우 1번의 경우와 같은 것 같지만 button 변수가 함수내부에 있으므로 문제가 없습니다. dealloc함수에서 release를 호출할 일도 없고 또한 new, alloc, init함수등으로 객체를 생성한 것이 아니기 때문에 자동 release되므로 문제 없습니다.


반면 4의 경우처럼 autorelease를 붙이거나 5번의 경우처럼 release를 했다면 스택오버플로우(?)와 같은 현상이 발생합니다.


6, 7번의 경우는 alloc, init, new함수를 썼으므로 release나 autorelease를 사용했습니다.. 이 경우에는 문제없습니다.


하지만 8번의 경우 retain되었고 addSubview가 되는 순간 두번째 retain이 됩니다.  내부적으로 addSubView에대한 것은 자동 release되겠으나 dealloc함수등에서 release시키지 않으므로 메모리 leak이 발생합니다. 이는 Instruments를 이용해서 찾을 수 있을겁니다.


retain과 release를 적절히 사용하는게 무엇보다 중요합니다. 개발하면서 항상 체크하세요.


이 개념을 잡는데 가장 도움이 되었던 글은 문씨님 글인것 같습니다.

http://cafe.naver.com/mcbugi/71504 

글쓴이 : 지돌스타(http://blog.jidolstar.com/730)


UISegmentedControl을 기본 스킨만 사용하는 경우야 문제는 없습니다.
하지만 대부분의 경우 그렇지 못하죠.
저처럼 아이폰 개발을 처음 하는 경우에는 전체 개발의 80%이상은 UI에 시간을 쏟아붙는듯 합니다.
분명 시간이 매우 아깝지만 익숙해지면 20~30%로 내릴 수 있을것이라 생각합니다.

각설하고....
UISegmentedControl의 기본 스킨은 다음과 같습니다. UIToolBar에 [[UIBarButtonItem alloc]initWithCustomView:]를 이용해 등록하면 아래와 같이 됩니다.


기본스킨을 사용하면 아무 문제없이 선택이 잘됩니다.

하지만 UISegmentedControl의 tintColor를 [UIColor blackColor]로 지정하면 아래 처럼 보이게 되는데 실제로 실행해보면 선택되어지지 않습니다. 정말 난감해지는 순간입니다. 선택했을때 색, 선택되지 않았을때 색, 글자색 뭐 이런것들을 직접 다룰 수 있는 함수나 속성이 전혀 있지 않아 매우 난감했습니다. 다른 분들은 이것을 어찌 해결하셨는지 궁금할 정도입니다.



제가 하고자 했던 목표는 글자크기를 크게하고 선택이 될 수 있는 모습을 보고 싶다는 겁니다.
아주 아주 단순한 요구사항인데도 불구하고 속성변경으로 단순하게 처리할 수 없어 너무 답답합니다. 어쨌든...
해결하기 위해 구글신의 도움을 빌릴 수 밖에 없더군요. 그러다가 다음 내용을 찾았습니다.

iPhone: UISegmentedControl with custom colors
iPhone – Get Class Name

Change font size for text in UISegmentedControl

(아래 내용은 설명이라고 적었지만 소스를 먼저 분석하시고 보시는 편이 더 좋을 것 같습니다. ^^)
첫번째 내용은 UISegmentedControl을 확장해서 선택할때 배경색이 바뀌도록 한 것입니다. 이 사람은 이것을 쓴 어플이 문제없이 등록승인되었다고 하네요. 그러니 우리도 쓸 수 있습니다. ^^ 단지 이 소스의 단점은 UISegmentedControl의 selectedSegmentIndex를 0이 아닌 1,2 등으로 지정하면 오동작 한다는 겁니다. 당신의 어플에서 기본 0이 항상 선택되어야 하는 경우라면 전혀 문제 없겠지만 1, 2 등이 선택되어야 한다면 당연히 문제가 생기므로 이 마저도 수정해야합니다. 제가 선택한 방식은 UIView의 tag를 이용한 것입니다. UISegmentedControl의 내부에 생성된 것들은 검사해 보니 UISegment입니다. 이 클래스는 private로 지정되어 애플 정책상 직접 사용하는 것이 금지됩니다. 하지만 문제 해결을 위한 참조정도는 가능한가 봅니다. 이 UISegment가 "하나","둘","셋" 순서대로 인덱스를 0,1,2로 지정되어 있으면 문제 없는데 또 그런 것도 아닌 것 같더군요. UIView의 subviews속성을 통해 얻어온 자식들을 가지고 손쓰면 안된다는 것을 의미합니다. 그래서 UIView의 tag 를 사용합니다. ^^

세번째 내용은 폰트를 설정하기 위해 사용합니다. 내용을 보면 changeUISegmentFont 라는 함수를 설명하고 있는데요. 이것은 재귀함수로 UISegmentContoller에 자식뷰를 전부 돌면서 UISegmentLabel을 찾아 폰트를 수정해주는 식입니다. 하지만 이것은 직접쓰면 안되고 클래스의 이름을 가져오는 과정에서 두번째 내용이 필요하고 직접 쓴다고 해서 폰트가 변경되는 시점은 비동기적으로 동작하기 때문에 처음 생성시 변경해준다고 해서 되는 문제는 아닙니다. 첫번째 내용에 이 함수를 함께 쓴다면 어느정도 문제 해결의 실마리를 찾게 되더군요.

이제 소스 들어갑니다.
헤더 입니다. 이름은 CustomSegmentedControl이라 정했습니다.

//

//  CustomSegmentedControl.h

//

//  Created by Yongho Ji on 10. 9. 15..

//


#import <Foundation/Foundation.h>



@interface CustomSegmentedControl : UISegmentedControl {

UIColor *offColor; //off 배경색

UIColor *onColor; //on 배경색

UIColor *onTextColor; //off 글자색

UIColor *offTextColor; //on 글자색

int fontSize; //글자의 크기 

}


-(id)initWithItems:(NSArray*)items 

  offColor:(UIColor*)offcolor 

  onColor:(UIColor*)oncolor 

  offTextColor:(UIColor*)offtextcolor 

  onTextColor:(UIColor*)ontextcolor 

  fontSize:(int)fontsize;


@end



다음은 구현부입니다. 천천히 따라가 보시면 해석하시는데 무리는 없을겁니다.

//

//  CustomSegmentedControl.m

//

//  Created by Yongho Ji on 10. 9. 15..

//


#import "CustomSegmentedControl.h"



@implementation CustomSegmentedControl


//UISegment계열 폰트의 색과 크기를 조절시켜준다. 재귀적으로 찾아가는 것을 눈여겨 보자.

- (void)_changeUISegmentFont:(UIView*) aView 

fontSize:(int)fontsize 

  textColor:(UIColor*)textcolor 

{

NSString *typeName = NSStringFromClass([aView class]);

if([typeName compare:@"UISegmentLabel" options:NSLiteralSearch] == NSOrderedSame) {

UILabel *label = (UILabel*)aView;

UIFont *font = [UIFont boldSystemFontOfSize:fontSize];

[label setFont:font]; //글자크기 지정 

[label setTextColor:textcolor]; //글자색 지정 

//글자크기에 따라 위치/크기 보정 

CGSize size = [label.text sizeWithFont:font forWidth:320 lineBreakMode:UILineBreakModeClip];

[label setFrame:CGRectMake(0, 0, size.width, size.height)];

[label setCenter:CGPointMake(label.superview.frame.size.width/2, label.superview.frame.size.height/2)];

}

NSArray *subs = [aView subviews];  

NSEnumerator* iter = [subs objectEnumerator];

UIView *subView;

while (subView = [iter nextObject]) {

[self _changeUISegmentFont:subView fontSize:fontsize textColor:textcolor];

}


//색이 바뀔때마다 Segment 배경색과 폰트색을 바꿔준다.

-(void)_setToggleHiliteColors {

//NSLog(@"%d",self.selectedSegmentIndex);

int index = self.selectedSegmentIndex;

int numSegments = [self.subviews count];

id subview;

//리셋 선택 처리 

//   깜박임이 존재하는 것은 UISegmentedControl 내부적으로 폰트 색을 그렸다가 

//   여기서 강제로 다시한번 지정하기 때문에 그렇다

//   어찌할 방법을 찾지는 못했지만 그럭저럭 쓸만함 

for (int i=0; i<numSegments; i++) {

subview = [self viewWithTag:i];

if (i==index) { //선택

[subview setTintColor:nil];

[subview setTintColor:onColor];

[self _changeUISegmentFont:subview fontSize:fontSize textColor:onTextColor];

} else { //리셋

[subview setTintColor:nil];

[subview setTintColor:offColor];

[self _changeUISegmentFont:subview fontSize:fontSize textColor:offTextColor];

}

}

}


//초기화 함수 

-(id)initWithItems:(NSArray*)items 

  offColor:(UIColor*)offcolor 

  onColor:(UIColor*)oncolor 

  offTextColor:(UIColor*)offtextcolor 

  onTextColor:(UIColor*)ontextcolor 

  fontSize:(int)fontsize 

{

if (self = [super initWithItems:items]) {

// 폰트크기 지정 

offColor = [offcolor retain]; 

onColor = [oncolor retain];

offTextColor = [offtextcolor retain];

onTextColor = [ontextcolor retain];

fontSize = fontsize;

//스타일 고정 

[self setBackgroundColor:[UIColor clearColor]];

[self setSegmentedControlStyle:UISegmentedControlStyleBar];

//루프를 돌면서 태그를 달아줌 

id subview;

for (int i=0; i<[self.subviews count]; i++) {

subview = [self.subviews objectAtIndex:i];

[subview setTag:i];

}

//listen for updates

[self addTarget:self action:@selector(_setToggleHiliteColors) forControlEvents:UIControlEventValueChanged];

//비동기적으로 한번 호출해준다. 글자크기/배경색 적용을 위해...

[self performSelector:@selector(_setToggleHiliteColors) withObject:nil afterDelay:0.1];

}

return self;

}


//메모리 dealloc

-(void)dealloc {

[offColor release];offColor=nil;

[onColor release];onColor=nil;

[onTextColor release];onColor=nil;

[offTextColor release];offTextColor=nil;

[super dealloc];

}


@end



이제 만들어진  CustomSegmentedControl을 사용하는 예제 호스트 코드입니다.  복잡해 보이지만 IB에서 ToolBar 붙이고 거기에 UISegmentedControl을 중앙에 붙이기 위한 작업을 코드로 옮겨 넣은 것 뿐입니다.

UIToolbar *tb = [[[UIToolbar alloc]init]autorelease];

[tb setFrame:CGRectMake(0, 480-49, 320, 49)];

[tb setBarStyle:UIBarStyleBlack];

[window addSubview:tb];

CustomSegmentedControl *segControl;

segControl= [[CustomSegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@"하나 ",@" ",@" ",nil

  offColor:[UIColor blackColor]

  onColor:[UIColor colorWithRed:120.0f/255.0f green:120.0f/255.0f blue:120.0f/255.0f alpha:1]

  offTextColor:[UIColor colorWithRed:153.0f/255.0f green:153.0f/255.0f blue:152.0f/255.0f alpha:1

  onTextColor:[UIColor whiteColor]

  fontSize:15];

segControl.frame = CGRectMake(0, 0, 250, 35);

segControl.selectedSegmentIndex=1;

//[segControl addTarget:self action:@selector(_valueChanged) forControlEvents:UIControlEventValueChanged];

UIBarButtonItem *segControlItem = [[[UIBarButtonItem alloc]initWithCustomView:segControl]autorelease];

UIBarButtonItem *leftItem = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]autorelease];

UIBarButtonItem *rightItem = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]autorelease];

[tb setItems:[NSArray arrayWithObjects:leftItem, segControlItem, rightItem, nil]];

[segControl release];


아래와 같이 선택했을때 색변경과 글자크기 변경이 가능해졌습니다.


좋은 지식이 되었으면 하며, 다른 의견 있으시면 댓글 부탁합니다. ^^

글쓴이 : 지돌스타(http://blog.jidolstar.com)

위 화면은 UINavigationBar 를 보여주고 있습니다.
오른쪽을 보면 버튼이 3개가 붙어 있습니다.
어떻게 한것일까요? 저도 어떻게 할 수 있을까 무척 고민했습니다.
일단 저기에 뭔가 붙이려면 UIViewController에서 self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]init...]autorelase]을 설정해주면 됩니다.

- initWithBarButtonSystemItem: target: action:
- initWithImage: style: target: action:
- initWithTitle: style: target: action:

위 함수중 1개를 선택해서 객체를 생성할 수 있는데 전부 1개만 넣을 수 있습니다. 2개 이상은 안되죠. 다행히도 아래와 같은 함수가 있습니다.

-initWithCustomView:

이 함수를 이용하면 UIView를 확장한 객체만 뭐든지 들어갈 수 있지요. 당연하지만 앞의 3개의 함수와 달리 버튼을 눌렀을때 액션을 취할 수는 없습니다. 이것은 커스터마이징 해야할 겁니다.

그럼 처음 위 Navigation Bar에서 보여준것처럼 하게 하려면 결국 UIView로 하면 됩니다.
하지만 UIView를 이용하면 위치를 일일히 지정하는 번거로움이 있어서 이런 경우에는 UIToolBar를 사용하면 되겠죠. 즉 아래처럼 하면 됩니다.

self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:myToolBar]autorelease];

결과는 예~ 잘등록됩니다. ^^

하..지..만... 요래 됩니다.




당연하겠죠. UIToolBar 기본배경이 원래 저거니깐요.

이제 배경색만 지우면 되겠지 싶어
myToolBar.opaque = NO 도 해보고...
myToolBar.translucnet = YES 도 해보고...
myToolBar.backgroundColor = [UIColor clearColor] 도 해보고
myToolBar.tintColor = [UIColor clearColor] 도 해보고....

별짓을 다해봤지만.... 배경색이 지워지지 않더군요. 인터넷 뒤져봐도 투명으로 만드는 방법 말고는 설명된 것을 찾기가 어렵더군요. 그냥 UIView 확장해서 만들까 하지만 오기가 생겼습니다.

이리저리 찾아보다가.... 방법을 찾았습니다.

- (void) drawRect:(CGRect)rect {}

결국 위 함수를 오버라이드 해서 내부에 아무것도 정의하지 않으면 된다는 사실을 깨달았습니다.
말그대로 UIToolBar를 확장해서 아래처럼 아무 코드도 넣지 않으면 됩니다.

- (void) drawRect:(CGRect)rect {
    //이것으로 배경을 그리지 않는다.
}

그리고 내부적으로 아래와 같은 코드가 들어가야 합니다. init함수에 아래 코드를 넣으면 완성됩니다.

self.translucent= YES; 


저 버튼들을 눌렀을때 action은 어떻게 처리하냐고요? 그야 방법은 아주 많겠죠? 그건 나름 연구해보시길.... ^^

글쓴이 : 지돌스타(http://blog.jidolstar.com/728)
일반적으로 키보드를 감추기 위해  [myTextField resignFirstResponer] 메소드를 사용하실 겁니다.
UIViewController가 전환할때는 기존 ViewController에 떠 있던 키보드가 자동으로 감춰집니다. 

하지만  firstResponder의 출처를 찾기가 곤란한 경우도 있습니다. 가령.. 저의경우 
중간에 네트워크가 중지되거나 점검페이지등을 붙일때 Controller가 아닌 UIView를 직접 사용해 window의 최상위에 붙이게 되는 경우가 있는데, 이때 ViewController에 키보드가 보여져 있으면 이 페이지 위에 키보드가 그대로 남게 되는 경우가 발생합니다.

꼭 위와 같은 경우가 아니더라도 키보드가 어디를 기준으로 보이든지 감춰줄 수 있는 메서드가 필요했습니다.
저는 아래 메서드를 공통으로 사용할 수 있는 클래스(가령 AppDelegate)에 정의해놓고 언제든지 키보드를 감출 수 있도록 합니다.
여기서 호출할 메소드는 hideKeyboard  입니다. _hideKeyboardRecursion은 제귀함수로 직접 호출하지는 않습니다.

//키보드를 사라지게 하기 위해 사용하는 재귀함수 

- (void)_hideKeyboardRecursion:(UIView*)view 

{

if ([view conformsToProtocol:@protocol(UITextInputTraits)]) 

{

[view resignFirstResponder];

}

if ([view.subviews count]>0

{

for (int i = 0; i < [view.subviews count]; i++) 

{

[self _hideKeyboardRecursion:[view.subviews objectAtIndex:i]];

}

}

}


//키보드 감추기

- (void)hideKeyboard 

{

UIWindow *tempWindow;


for (int c=0; c < [[[UIApplication sharedApplication] windows] count]; c++) 

{

tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:c];

for (int i = 0; i < [tempWindow.subviews count]; i++) 

{

[self _hideKeyboardRecursion:[tempWindow.subviews objectAtIndex:i]];

}

}

}


혹시 부족한 점 있으면 보완 부탁드릴께요. 

글쓴이 : 지돌스타(http://blog.jidolstar.com/727)

이 내용은 검색해도 제대로 나와 있는게 없어서 간단히 정리하여 공유하는 수준입니다.

 

APNS에 관심을 가지시는 분들이 많을겁니다.

APNS는 프로바이더가 Push서비스를 하기 위한 시스템 구축할 필요없이 Apple을 도움을 받아 구현할 수 있기 때문에 적은노력으로 최대한의 효과를 볼 수 있는 아주 유용한 서비스이지요.

 

APNS를 접하다 보면 헷갈리는게 있습니다.

 

Provisioing Portal에 들어가면 APNS가 2가지 종류라는 겁니다.

1. 개발버전

2. 배포버전

 

개발버전 APNS는 Provisioning Profile에서 Development와 연관 있습니다. 단순히 Xcode상에서 디바이스로 디버깅할때 유용합니다.

배포버전 APNS는 Provisioning Porfile에서 Distribution과 연관 있습니다. 이는 Adhoc이든 AppStore든 상관없습니다.

 

이렇게 구분된 이유는 저는 개발할때와 배포할때 APNS가 동일하면 발생되는 문제점을 해소하기 위함이라고 이해했습니다.

만약 개발과 배포시 APNS가 동일하다면 서비스하는 도중에 개발하면서 잘못된 APNS를 사용자들에게 보내버릴 수 있는 경우가 발생할 수 있습니다. 이러한 상황을 미연 차단한 것이라고 생각됩니다.

 

그럼... 두가지 버전의 명확한 차이는 무엇일까요?

 

첫째, 바로 발행하는 인증서가 다르겠죠? 인증서는 App ID에서 발행하므로 어플마다 다릅니다.

 

둘째, Device Token 값이 다릅니다. 개발버전의 Device Token과 배포버전(Adhoc, Appstore)의 Device Token은 다릅니다. 이것은 어플마다 다르지 않고 Device마다 다릅니다. 하지만 기기의 고유 UUID와는 다릅니다.

 

셋째, 그리고 프로바이더(java든, php든 상관없이) 입장에서 gateway 주소가 다릅니다. 개발버전에서는 gateway.sandbox.push.apple.com 에 접속하고 배포버전에서는 gateway.push.apple.com에 접속합니다. 포트번호는 둘다 2195이지요.

 

이 부분에 대해서 명확하게(그것도 한글로.. ^^;) 설명한 내용이 없었습니다.

제가 영어를 잘해서 Apple문서를 정독했더라면 알 수 있는 내용이였지만.... 결국 삽질끝에 파악한 내용이네요. ㅎㅎㅎ

 

아무튼 유용한 정보가 되었길...

 

다른 유용글

[iPhone/Java] 내가 만든 어플에 Push Notification 적용하기

APNS Device Token을 못받아올때

글쓴이 : 지돌스타(http://blog.jidolstar.com/724)

 

Error: Error Domain=NSCocoaErrorDomain Code=3000 "응용 프로그램에 대해 발견된 'aps-environment' 인타이틀먼트 문자열 없음" UserInfo=0x117d00 {NSLocalizedDescription=응용 프로그램에  발견된 'aps-environment' 인타이틀먼트 문자열 없음}

 

AppDelegate에서 DeviceToken을 받지 못하고 Error 메시지를 띄우는 경우가 있습니다.

분명 Development나 Adhoc Provisioning Profile을 받아서 정상적으로 컴파일 했는데도 발생되는 문제입니다.

위와 같은 내용이 들어오면 다음 방법으로 문제를 해결합니다.

(디바이스에서 테스트 경험이 있는 분들만 이해하실 수 있습니다.)

 

1. iOS Provisioning Portal 에 갑니다.

2. App IDs 메뉴로 들어가 APNS를 Enabled 시킵니다.

3. Provisioning 메뉴으로 들어가 이전 Profile을 지웁니다.(Development와 Distribution 모두)

4. 거기서 다시 새로운 Profile을 생성합니다.

5. Xcode의 Organizer에 등록되어 있는 Provisioning Profile은 지웁니다.

6. 새로 생성한 Provisioning Profile을 다운받은후 두번 클릭으로 Organizer에 설치합니다.

 

이렇게 한뒤 디바이스에서 테스트 해보면 잘됩니다.

 

Provisioning Profile이라는 것은 Provisioning Portal에서 Certificate, Device, App ID 순서로 만들어진 결과물의 정보를 담습니다. 그러다 보니 세가지중에 하나라도 바뀌면 다시 Profile을 다시 생성해서 받아야 합니다. 위 에러의 경우 먼저 Profile을 받고 난다음 AppID에서 APNS를 활성화 시켜 Profile에는 이 정보가 포함되어 있지 않아 발생하는 문제였던 겁니다.

 

여기서 교훈은... Certificate, Device, App ID 에서 하나라도 수정되면 반드시 기존 Provisioning Profile을 지우고 재생성해서 받아 써야한다는 겁니다.

 

저... 이것때문에 완전 머리 쥐어 짰습니다. ㅜㅜ;;;;;

글쓴이 : 지돌스타(http://blog.jidolstar.com/725)

최근 아이폰 어플을 공부하고 개발하고 배포까지 하면서 개발시 꼭 체크하거나 염두해야할 일을 생각나는데로 정리해 보았다. 

 

1. 메모리는 항상 관리한다.

Instruments를 이용해 Memory leaks를 반드시 한다. 특히 View Controller가 전환시, 또는 데이터 통신후에 체크하도록 하는 것이 중요하다. Instruments를 이용하면 완벽하지 않지만 문제를 해결할 수 있는 발판을 마련해준다.

 

또한 Build만 해보지 말고 Build and Analyze를 통해 잠재적으로 메모리 leaks가 생길 부분을 찾도록 한다. 완벽하지 않지만 retain후 release를 안한 부분도 은근히 잘 찾아주므로 꼭 활용하길 바란다.

 

2. 디바이스 테스트는 필수

아이폰 시뮬레이터에서 동작을 잘하던 것이 디바이스에서 테스트 하면 중간에 멈추던가 이상한 동작할 하는 경우가 발생한다. 거의 대부분 이것은 메모리 문제이다. 디바이스는 제한된 메모리이기 때문에 메모리 경고가 자주 일어난다. 또한 이러한 메모리 문제는 View Controller에서 viewDidLoad 메소드를 다시 호출시켜 그에 따른 대책을 마련하지 않으면 어플이 죽거나 이상한 동작을 하게 된다.

 

디바이스에서 테스트는 개발 중간중간 자주 해야한다. 그렇지 않고 시뮬레이터에서만 개발하다가 디바이스에 올린뒤 발생하는 문제를 해결하려면 노력이 배 이상이 들 수 있다.

 

 

3. Memory Warning을 지나치지 말아라.

일단 아이폰 시뮬레이터의 메뉴를 보면 강제적으로 메모리 경고를 줄 수 있다. 그렇게 되면 AppDelegate와 View Controller에서 메모리 경고를 감지할 수 있게 된다. 경고가 발생하면 필요없는 자원을 해제 시키길 바란다. 또한 View Controller에서는 viewDidUnload 메소드가 호출될 수 있다. 이때 self.myView = nil 처리가 되어 있으면 이 객체는 메모리 반환이 되고 나중에 viewDidLoad와 viewWillAppear 호출된다. 이 때 중복된 메소드 호출이나 잘못된 메모리 반환으로 어플이 중간에 중지되거나 이상한 데이터를 View상에 보여주게 된다. 이런 처리도 말끔하게 해주어야 된다. 결국 View Controller의 라이프 사이클을 잘 이해하는 것이 중요하고 그에 따라 대처해야한다.

 

 

4. 인터페이스 빌더를 잘 활용하자.

개발자이기 때문에 인터페이스 빌더를 사용안하고 오로지 코딩으로 뷰배치를 하시는 분들이 있다. 초반에 아이폰 개발때는 이 방법이 좋을 수 있다. 무언가 코드안에서 다 해결할 수 있기 때문이겠다. 하지만 아이폰과 같은 작은 기기의 어플들은 긴 기간의 개발을 요구될 수 없다. 짧은 기간안에 빠른 승부를 내야하는게 바로 아이폰 어플이라고 본다. 뭔가 View 구성을 코드로만 하다 보면 개발자는 나중에 지쳐버린다. 한 페이지 View를 만드는데 만해도 엄청난 노력이 들어가야 한다.

 

인터페이스 빌더를 이용해 ViewController 단위로 만들고 TableView에 보일 Cell들도 만들면 여러분은 어느정도 View 구성하는 스트레스에서부터 해방될 수 있다. 완벽하지 않지만 복잡한 배치를 위해 골머리 쌓는 일에서는 거의 70~80% 해방된다. 게다가 ViewController의 코드도 많이 짧아진다. 왜냐하면 View를 구성하기 위한 코드가 많이 줄기 때문이다.

 

또한 인터페이스 빌더를 이용하면 Command+R 만으로 시뮬레이터에서 View를 미리 볼 수 있다. 이런 것들을 활용하면 개발에 많이 도움된다.

 

 

5. SVN을 이용한 소스 관리를 꼭 하자.

개발하면서 소스관리 툴하나 쓰지 않는다는 것은 사실 말이 안된다. Eclipse와 같은 툴을 다뤄봤던 사람이라면 소스관리를 위해 SVN을 많이 사용했을 것이다. 협업을 위한 것도 있지만 개인적으로 쓰더라도 소스 관리는 반드시 필요하다. Xcode는 기본적으로 SCM 기능이 있어 이것으로 소스관리가 가능하다. Eclipse에 비해서 많이 불편한 편이지만 익숙하면 쓸만하다.

 

6. 최적화에 만전을 기하자.

아이폰은 데스크탑과 다르게 제한된 메모리, 제한된 CPU 기반이다. 그러므로 이런 제한된 환경에서도 부드럽게 동작하도록 노력해야한다. 가령 이미지를 프로세싱 하더라도 cache처리를 해야할지 말아야 할지, Thread나 Operator를 이용해 데이터를 가져오거나 말아야할지 등을 잘 결정해서 개발해야한다. 까페에 문씨님이 올린 Operator 활용법을 참고하면 좋겠다.

 

7. 다양한 장치에서 구동되도록 하자.

애플 개발 정책(?)상 xcode를 배포하면서 번들로 있는 SDK는 항상 최신을 유지한다. 그래서 구버전의 아이폰이나 아이팟 터치에 동작하도록 만들 필요가 있다. iOS 4 기반으로 개발하더라도 약간의 옵션 조정으로 3.0, 3.1 에서도 동작하도록 할 수 있다. 그것은 Groups & Files에서 어플의 이름을 선택한뒤 info에서 Build 탭을 선택한다. 거기서 iOS Deployment Target을 iOS 3.1 등으로 맞추면 가능하다. 물론 SDK 상에서 상위버전시에만 구동이 되는 부분에 대해서는 따로 조치를 취해야 하며 장치 구성상 전혀 사용할 수 없는 부분은 아에 AlertView등으로 알려줘야한다. 가령 카메라의 경우 구형 아이팟터치는 동작하지 않듯이 말이다.

 

8. [myObject release]; 후에는 반드시 myObject=nil 을 하자.

@property로 지정된 속성의 경우 self.myObject = nil 하는 것만으로도 [myObject release];myObject=nil; 이 진행된다. 하지만 속성이 @property로 지정되어 있지 않은 경우에는 self.myObject로 접근할 수 없으므로 release만 할 수 있다. 하지만 [myObject relase];만 하면 문제가 발생할 수 있다. 가령, release를 한뒤 retainCount가 0가 되면 이것은 이제 좀비가 된다. 이 좀비객체에 어떠한 메시지를 보내면 무조건 어플 죽는다. 하지만 myObject=nil 처리하면 nil에 어떤 메시지를 보내도 무시해버린다. 이러한 문제는 좀처럼 눈에 보이지 않게 어플을 죽게하는 요인이 된다. 정상적인 상황에서는 이런 문제가 안생기는데, 디바이스에 물려서 돌리면 어플 죽은 범인이 여기에도 있다. 왜냐하면 디바이스는 제한된 메모리로 waning이 빈번하게 날 수 있고 그에 따라서 viewDidLoad등이 다시 호출되면서 좀비가된 myObject를 엑세스해버리는 현상이 발생할 수 있기 때문이다. release후 다시 새로운 객체로 할당해 retain 하더라도 그냥 버릇처럼 [myObject release];myObject=nil; 이런식으로 하는게 좋다.

 

 

이외에도 많겠지만 일단 생각나는데로 정리해보았다.


글쓴이 : 지돌스타(http://blog.jidolstar.com/724)

아이폰 개발시작한지 3~4개월 되어가면서 조금 감각을 익히기 시작했습니다. 
어플도 그동안 3개 만들어 올려보고요.  

물론 사운드, 그래픽을 고급스럽게 다뤄보지는 못했지만 기본 UI기반으로 개발할때도 워낙 이슈가 많다보니 학습과 개발을 병행하는게 정말 쉽지 않더군요.... 

각설하고요 ㅎㅎ

여기에 소개할 것은 UIImageView에 원격 이미지를 비동기로 로드할 수 있도록 하는 기능과 이미지 캐쉬 기능을 추가한 소스를 공개하려고 합니다.(소스 분석은 주석을 참고 ^^)

아이폰 어플 개발하면 UIImageView를 매우 많이 사용할 겁니다.  번들이미지의 경우야 어짜피 문제 없지만 원격이미지를 로드할때는  몇가지 이슈가 발생합니다.

1. 원격이미지를 매번 로드하는 것은 네트워크 부하를 일으키며 특히나 3G사용자들에게 치명적이 될 수 있다.
2. 테이블에 원격이미지를 붙이는 경우에 동기적으로 이미지 로드하는 경우 멈춤 현상을 일으킬 수 있다. 
3. 비동기적으로 이미지를 로드하더라도 한번에 로드할 수 있는 이미지를 제어하지 않으면 어플의 전체적인 퍼포먼스가 죽는다.
4. TableView에서 TableViewCell는 캐쉬처리되어 재사용된다. 그러므로 거기에 붙은 UIImageView도 재사용하게 되는데 스크롤을 빨리 넘기는 경우 기존에 로드 요청한 이미지가 하나의 UIImageView에 계속 적재되는 현상이 발생할 수 있다.

위 이슈에서 1, 2는 금방 이해갈 갈겁니다. 3번의 경우 1,2번의 처리가 잘되었다고 해도, 한 화면에 5개 이상의 이미지를 비동기적으로 로드한다는 것은 스레드를 5개 이상 생성해서 처리한다는 의미와 같습니다. 어플 하나에 스레드를 너무 돌리면 별로 좋지 못하기 때문에 동시에 로드할 수 있는 이미지를 제어해주어야 합니다. 1~2개 정도로요. 
4번 이슈의 경우 예전에 문씨님이 올려주신 [문씨의 강좌]멀티스레딩2<NSOperation>에 올린 글에 소개된 소스의 경우에 발생합니다. 저는 여기에 이미지 캐쉬기능만 넣어서 실제로 썼습니다. 하지만 TableView에서 문제가 발생했습니다. 분명 NSOperation을 이용한 이미지 로드는 2,3 문제를 해결해줍니다. 하지만 TableViewCell을 재사용되기 때문에 빠른 스크롤을 하는 경우 거기에 붙은 UIImageView 하나에  지속적으로 다른 이미지가 붙도록 요청이 되어 이미지가 광고롤링되는 현상마냥 보이는 경우가 발생합니다. 

1,2,3,4 번의 이슈를 모두 해결하고자 간단하게 클래스를 제작했습니다.

사용하는 방법은 너무도 간단합니다. 그저 UIImageView를 붙히고 (IB에서든 코드상이든) #import "UIImageView+AsyncAndCache.h"를  넣습니다. 그 다음 아래 UIImageView 카테고리 4개 함수중 하나를 쓰시면 됩니다.  UIImageView *imageView = [[UIImageView alloc]init]; 하신뒤 [imageView setImageURLString:@"이미지 원격 경로"]; 형태로 쓰시면 됩니다. 

UIImageView를 카테고리로 만들었으므로 기존 UIImageView 기능은 그대로 사용할 수 있겠고요.

UIImageView 카테고리 외에 내부적으로 2개의 클래스가 정의되어 있습니다. 이는 개발자가 직접 제어하지 않고 위 4개 이슈를 해결하기 위해 내부적으로 사용되는 클래스입니다. 소스 분석을 원하신다면 주석을 달아두었으니 참고하시면 되겠습니다.

아래는 header만 올려놓습니다. 구현부는 첨부파일을 참고하세요.

uiimageview asyncandcache.zip


ARC환경에서는 아래것을 사용하면됩니다.(오래된 글이라... 개선여지가 많습니다. )

UIImageView AsyncAndCache.zip



//

//  UIImageView+AsyncAndCache.h

//

//  Created by Yongho Ji on 10. 12. 3..

//  Copyright 2010 Wecon Communications. All rights reserved.

//


#import <UIKit/UIKit.h>


@class AsyncAndCacheImageOperator;

@class AsyncAndCacheImageOperatorManager;


//////////////////////////////////////////////////////////////

//

// UIImageView 대한 카테고리 

// 카테고리는 테이블뷰에 적용된 Cell안에 UIImageView에서 활용하면 좋다.

// UIImageView 주요 기능은 다음과 같다

//

// 1. 이미지 비동기 로드 

//   이미지를 비동기로 로드해서 화면에 이미지가 뜨는데 버벅거림을 없앤다.

// 2. 이미지 캐쉬기능 

//   이미 로드한 이미지는 cache 디렉토리에 캐쉬해서 나중에 반복 요청시 

//   로컬에 저장된 캐쉬 이미지를 로드해서 네트워크 부하를 없애준다.

// 3. 반복적인 이미지 요청에 대한 로드부하 최소화 

//    같은 UIImageView 중복으로 로드 요청한다면 마지막에 요청한 이미지가 적용되도록 한다.

//    그뿐 아니라 수십번 반복해서 요청하더라도 무조건 이미지 로드 요청하지 않고 되도록이면 

//   마지막 이미지를 로드요청하여 네트워크 부하를 줄여준다

// 

// 개선해야할 사항 

//

// 1. 캐쉬기능 강제삭제기능 

// 2. 지정된 시간이 지난 캐쉬 이미지 자동 삭제기능 

// 3. 캐쉬사용여부 결정기능  

// 

//////////////////////////////////////////////////////////////


@interface UIImageView (AsyncAndCache)


//String형태의 이미지 URL 초기화

-(id)initWithURLString:(NSString*)url;


//NSURL 형태의 이미지 URL 초기화 

-(id)initWithURL:(NSURL*)url;


//String형태의 이미지 URL 셋팅 

-(void)setImageURLString:(NSString*)url;


//NSURL 형태의 이미지 URL 셋팅 

-(void)setImageURL:(NSURL*)url;


//동시에 로드할 이미지 최대수  

+(void)setMaxAsyncCount:(NSUInteger)count;


@end


//////////////////////////////////////////////////////////////

//

// 한개의 ImageView 대한 오퍼레이터이다.

// 비동기적으로 로드하는 것을 지원하며 더불어 캐쉬기능까지 지닌다.

// 개발자가 클래스를 직접 사용하지 않는다.

// 클래스는 AsyncAndCacheImageOperatorManager 클래스에서 동작/관리한다.

//

//////////////////////////////////////////////////////////////

@interface AsyncAndCacheImageOperator : NSObject

{

NSURL *_url; //로드할 이미지의 URL 정보 

UIImageView *_imageView; //이미지를 적용할 View

BOOL _canceled; //이미지 적용을 막는다. UIImageView 재사용시 나중에 로드되더라도 이게 YES이면 적용하지 못하도록 해서 사용자들로 하여금 잘못된 이미지가 로드되는 것을 방지 한다.

id _loadCompleteTarget; //이미지 로드가 완료되었을때 호출할 target

SEL _loadCompleteSelector; //이미지 로드를 완료했을때 호출할 selector

}


@property (readonly) UIImageView *imageView;


//초기화 함수 

- (id)initWithURL:(NSURL*)url imageView:(UIImageView*)imageView;


//스레드 적용 함수 

- (void)main;


//이미지 적용 취소

//main 메서드가 실행중일때 스레드자체는 중단시킬 없지만 imageView 로드한 image 적용하는 것은 방지시킨다.

- (void)cancel;


//이미지 로드 완료후 호출할 target/selector 적용 

- (void)setLoadCompleteWithTarget:(id)target selector:(SEL)selctor;

@end


//////////////////////////////////////////////////////////////

//

// ImageView정보를 담은 여러개의 오퍼레이터(AsyncAndCacheImageOperator클래스 객체) 관리한다.

// 개발자가 클래스를 직접 사용하지 않는다.

// setMaxAsyncCount 이용해 한번에 로드할 있는 이미지 갯수를 설정할 있다.

// 중요한 것은 동일한 UIImageView 대해서 다른 이미지 로드 요청이 있는 경우 

// 마지막에 요청한 이미지가 붙도록 하며, 같은 UIImageView 이미지 로드 대기중인 경우에는 

// 이전 UIImageView 대한 Operator 삭제함으로써 부적절한 로드로 인한 네트워크 부하를 최소화 해준다.

//

//////////////////////////////////////////////////////////////

@interface AsyncAndCacheImageOperatorManager : NSObject

{

@private

NSUInteger _maxAsyncCount; //동시에 비동기적으로 로드할 이미지 갯수 

NSUInteger _currentAscynCount; //현재 비동기적으로 로드하고 있는 이미지 갯수 

NSMutableArray *_standByImageOperators; //대기중인 Image Operator

NSMutableArray *_loadImageOperators; //로드중인 Image Operator 

}


//한번에 로드할 있는 이미지 갯수(스레드 최대 갯수)

-(void)setMaxAsyncCount:(NSUInteger)count;


//오퍼레이터 추가 

-(void)addImageOperator:(AsyncAndCacheImageOperator*)imageOperator;


@end



제 소스는 많은 테스트는 거치지 못했습니다. 그러므로 여기 개발자 분들께서 필요하시다면 제 소스를 분석하고 수정하면서 개선해주셨으면 합니다.  

----------------------------
수정사항 1
http://cafe.naver.com/mcbugi/95095 에도 이 글을 올렸습니다.
역시 소스가 공개되니 많은 분들이 테스트도 해주시고 좋네요. 만약 이미지 경로가 image.php?ggg=465.jpg로 되어 있다면 ?ggg=465.jpg 부분을 제대로 가져오지 못하는 버그가 있더군요. [_url path]로 되어 있는 부분을 [_url absoluteString]으로 하면 괜찮다고 합니다. 수정해서 쓰세요. 

수정사항 2
초기에 이미지가 붙어 있는데 주어진 이미지 경로에 이미지를 못불러오는 경우 image = nil이 되기 때문에 초기 이미지를 지우는 부분으로 이상하시다는 분도 계셨습니다. 이 부분은 아래처럼 처리하세요.

if (_canceled==NO) 
{
// 이 부분 추가
if (image)
_imageView.image = image;
}

if (_loadCompleteTarget!=nil) 
{
[_loadCompleteTarget performSelectorOnMainThread:_loadCompleteSelector withObject:self waitUntilDone:YES];
}


수정사항 3
이미지가 제대로 로딩이 안되는 버그가 있는데 메인스레드 관련 문제 때문입니다. 아래처럼 수정하세요.

if (_canceled==NO) {

    dispatch_sync( dispatch_get_main_queue(), ^{

        _imageView.image = image;

        [_imageView performSelector:@selector(layoutIfNeeded) withObject:nil];

    });

}


글쓴이 : 지돌스타(http://blog.jidolstar.com/723)


#ifdef ~ #else ~ #endif 
#define 

위 구문은 C, C++ 계열을 경험한 분들이라면 익숙한 내용일겁니다.
Xcode상에서 이것을 적절하게 활용하는 방법을 간단히 소개합니다.

커스텀 로그출력 

#ifdef USE_LOG

#define NSLog( s, ... ) NSLog(@"%s(%d) %@", __FUNCTION__, __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__])

#else

#define NSLog( s, ... )

#endif


위 코드처럼 사용한다면 USE_LOG가 정의되어 있으면 그 안에 있는 #ifdef~ #else 안에 정의된 #define 매크로가 사용되어집니다.  
즉 NSLog()사용시 커스터마이징된 NSLOG()로 출력해줍니다. USE_LOG가 정의되어 있지 않다면 #else ~ #endif내의 #define 매크로가 사용되어 지며  NSLog()를 사용한 모든 코드는 전부 무의미하게 만듭니다. 

이런 형태로 정의한 이유는 개발할때는 분명 상세한 로그가 필요하지만 배포시에는 필요없기 때문입니다. 개발시에 따로 커스터마이징된 NSLog를 사용하는 이유는 디버깅시에 좀더 상세한 로깅이 필요하고 NSLog()를 코딩하느라 힘빼지 않고도 단순히 원하는 내용만 삽입해도 어느 함수에서 실행된 건지, 몇번째 라인인지 등의 내용도 함께 출력해줄 수 있습니다. 

위 코드는 *.pch 에 넣어두시면 작성된 모든 코드에 적용됩니다. 꽤 유용하겠죠?


로컬,원격 접속 제어

#ifdef LOCAL 

#define _DEFAULT_URL @"http://localhost:8080"

#else

#define _DEFAULT_URL @"http://gateway.jidolstar.com"

#endif


위 방식의 경우 배포/개발에 상관없이 로컬테스트, 원격테스트를 각각 진행하고 싶을때 유용합니다. 가령, 일반 Debug시에는 로컬에서 테스트 해야하므로 LOCAL이 정의되어 있어야 합니다. 하지만 앱스토어에 올리는 경우라면 정의될 필요가 없는겁니다. Debug시더라도 Debug Local, Debug Remote로 나누어 관리할 필요도 있고 또는 배포라도 테스트 배포를 위해 Adhoc을 사용하는 경우는 Local, Remote로 나눠서 배포할 필요도 있을겁니다. 이럴때 이 방법은 유용합니다. 이 코드 또한 *.pch에 넣어두시면 됩니다.


사용방법
위 2가지 코드의 의미와 활용에 대해서는 언급했습니다. 하지만 구체적으로 어떻게 XCode상에 설정해야 저 코드를 사용할 수 있는지  설명하지 않았습니다.  

초반 프로젝트에 대한 Info에서 Build에는 Debug와 Release 설정만 있을겁니다.  Adhoc및 AppStore로 배포하기 위해서 이 설정을 두개 더 늘려 Debug, Release, Distribution Adhoc, Distribution AppStore 를 만들겁니다. 사실 위에서 언급한 내용이 없다면 이 정도로만 가져가셔도 테스트, 배포는 문제없습니다만...  로컬/원격 테스트를 빈번하게 진행해야한다던가 하는 경우라면 이야기가 좀 달라집니다. 위 코드에 필요한 #define을 매번 주석을 처리했다 풀었다 하는 것도 꽤 귀찮거든요. 

그래서 저는 Debug 를 하나더 카피해서 Debug Remote를 만들고 기존 Debug는 Local로 만듭니다. 
Distribution Adhoc도 Distribution Adhoc Local, Distribution Adhoc Remote 로 만듭니다. 하지만 Distribution AppStore는 로컬테스트는 진행하지 않으므로 그대로 둡니다.

그런다음 (맥 사파리에서는 네이버카페 글편집기가 이미지를 첨부할 수 없네요.)
Debug Local 설정을 선택후  Preprocess Macro 를 찾아 USE_LOG=1 LOCAL=1 을 입력합니다. 
Debug Remote 설정에는 Preprocess Macro에 USE_LOG 만 넣습니다.
Distribution Adhoc Local 설정에는 LOCAL=1 을 넣습니다. 
Distribution Adhoc Remote 와 Distribution AppStore 설정에는 아무것도 할필요가 없습니다.

이렇게 한다음 원하는 설정을 이용해 컴파일하는 것만으로 로그를 출력할지 말지, 로컬접속인지 원격접속인지 구분할 수 있게 됩니다. 

알고보면 진짜 별거 아닌데.... 이런 팁 하나하나가 생산성을 극대화 시키기 때문에 소개합니다.
좋은 팁 있으면 많이들 알려주세요. ^^

글쓴이 : 지돌스타(http://blog.jidolstar.com/722)
개인적으로 Flex, ActionScript 3.0 기반에서 개발을 오래도록 해와서 그런지 아이폰의 통지(Notification) 사용법이 꽤 낫설더군요.
그래서 ActionScript 3.0에서 사용되는 Event기반과 비슷하게 한번 만들어 봤습니다.

Event와 Notification은 비슷합니다.  하지만 사용하는 인터페이스가 불편함이 느껴졌습니다.

간단히 개념 설명이 들어가면... 
제가 만든 Event는 다음과 같은 용어를 씁니다.
1. 이벤트 송출자 ( Event Dispatcher)
2. 이벤트 (Event)
3. 이벤트 청취자 (Event Listener) 

이벤트는 데이터입니다. 이벤트가 발생(송출)할때 이벤트명,이벤트송출자,이벤트데이타를 담는 역할을 합니다. 이벤트는 이벤트 송출자가 만들고 이벤트 청취자가 받습니다.

이벤트 송출자는 이벤트를 만들어 보내는 역할을 합니다. 보낼때 이벤트를 송출하는 객체, 이벤트명, 그리고.. NSObject를 확장한 데이터를 담은 객체를 하나로 묶은 이벤트를 만들어주고 등록된 이벤트 청취자중 같은 이벤트명으로 등록된 청취자에게만 이벤트를 전달합니다. 

이벤트 청취자는 송출된 이벤트를 받습니다. 이벤트 청취자는 target/selector 를 지칭하며 청취자 등록시 함께 등록하는 이벤트명에 따라 실행됩니다. 즉, 이벤트 송출시 보내지는 이벤트명과 등록된 청취자의 이벤트 명이 같아야합니다. 반대로 이벤트 명이 다르면 절대 호출되지 않습니다. 


다음은 만들어진 소스의 header 코드입니다. 

//

//  Event.h

//

//  Created by Yongho Ji on 10. 10. 25..

//  Copyright 2010 Wecon Communications. All rights reserved.

//

// 이벤트를 다룬다. 내부적으로 Notification 기능을 한번 감싼형태이다

// 이렇게 만드는 이유는 호스트코드에서 쉽게 사용할 있게 하기 위함이다.

//


#import <Foundation/Foundation.h>


//=================================================

//

// 이벤트 

// 1. 내부 생성클래스이다

// 2. 개발자가 직접 생성하지 않는다.

// 3. 개발자는 등록된 이벤트 청취자로부터 이벤트 객체를 받게 되어 있다

//

//=================================================



@interface Event: NSObject

{

@private

id _dispatcher; // 이벤트 송출자

id _data; // 이벤트 데이타 

NSString *_eventName; // 이벤트  

}


@property (nonatomic, readonly) id dispatcher;

@property (nonatomic, readonly) id data;

@property (nonatomic, readonly) NSString *eventName;


@end



//=================================================

//

// 이벤트 청취자 

// 1. 내부 클래스이며 외부 노출되지 않는다.

// 2. 이벤트 청취 목록을 관리하기 위한 클래스이다

//

//=================================================

@interface EventListener : NSObject

{

@private

id _listener; //이벤트 청취자 

SEL _selector; //이벤트 청취자의 selector

NSString *_eventName; //이벤트 이름 

}


@property (readonly) id listener;

@property (readonly) SEL selector;

@property (readonly) NSString* eventName;


-(id)initWithListener:(id)listener selector:(SEL)selector eventName:(NSString*)eventName;

@end


//=================================================

//

// 이벤트 센터

// 1. 싱글톤 클래스이다.

// 2. [EventCenter defaultCenter] 접근해서 사용한다.

// 3. 이벤트 청취자 등록은 [[EventCenter defaultCenter]add:self selector:@selector(mySelector:) eventName:@"MY_EVENT"] 형태로 한다.

// 4. 이벤트 청취자 삭제는 3가지가 있다

//   - 1개의 이벤트 명에 대한 청취자 삭제 [[EventCenter defaultCenter] remove:self selector:@selector(mySelector:) eventName:@"MY_EVENT"] 형태로 한다.

// - 여러개의 이벤트 명에 대한 청취자 삭제 [[EventCenter defaultCenter] remove:self selector:@selector(mySelector:)] 형태로 한다.

// - 모든 이벤트 청취자 삭제 [[EventCenter defaultCenter] remove:self] 형태로 한다.

// 5. 이벤트 발송은 2가지 방법이 있다.

// - 데이터가 미포함된 이벤트 : [[EventCenter defaultCenter] dispatch:self eventName:@"MY_EVENT"] 

//   - 데이터가 포함된 이벤트 : [[EventCenter defaultCenter] dispatch:self eventName:@"MY_EVENT" data:myData]

//   - 데이터는 NSObject 확장한 것이라면 어떤 것이든 보낼 있다

//   - 이벤트가 발송되면 해당 이벤트 이름으로 등록된 모든 이벤트 청취자를 실행한다.

// 6. 이벤트 청취자는 listener selector 한묶음으로 본다. selector -(void)mySelector:(Event*)event; 또는 -(void)mySelector; 형태로 만들면 되겠다

//   , 인자로 Event객체가 오면 속성값에 dispatcher(이벤트를 발생한 ), eventName(이벤트명), data(이벤트시 보낸 데이타) 참조할 있다.

// 7. UIViewController기반에서 이벤트 등록과 삭제는 반드시 각각 viewWillAppear, viewWillDisappear에서 하도록 한다. 왜냐하면 등록된 이벤트 청취자 관리를 못하면 중복 호출이 있다.

//=================================================

@interface EventCenter : NSObject {

NSMutableArray *eventListeners;

}


//이벤트 기본 Center. 싱글톤 처리 

+(EventCenter*)defaultCenter;

//이벤트 청취자 등록 (중복된 등록은 무시됨)

-(void)add:(id)listener selector:(SEL)selector eventName:(NSString*)eventName;

//이벤트 청취자 삭제. selector, eventName 상관없이 같은 listener 등록되어 있으면 모두 삭제. 이미 삭제되어 있다면 무시

-(void)remove:(id)listener;

//이벤트 청취자 삭제. eventName 상관없이 같은 listener, selector 등록되어 있으면 모두 삭제. 이미 삭제되어 있다면 무시

-(void)remove:(id)listener selector:(SEL)selector;

//이벤트 청취자 삭제. listner, selector, eventName 모두 같아야 삭제된다. 이미 삭제되어 있다면 무시.

-(void)remove:(id)listener selector:(SEL)selector eventName:(NSString*)eventName;

//이벤트 송출. 데이터 미포함 

-(void)dispatch:(id)dispatcher eventName:(NSString*)eventName;

//이벤트 송출. 데이터 포함

-(void)dispatch:(id)dispatcher eventName:(NSString*)eventName data:(id)data;

@end


총 3개의 클래스로 구성되어 있으나 이벤트 송출자 등록, 이벤트 청취자 등록, 이벤트 송출은 모두 EventCenter 클래스가 관장하며, EventCenter는 싱글톤 처리되어 [[Event defaultCenter] ...] 형태로 접근이 가능합니다.

내부적으로 NSNotification을 한번 감싸서 통지를 이벤트로 추상화처리 한 것입니다. 

아마도 Objective-C의 NSNotification 또는 ActionScript의 Event를 사용해보신 경험이 있는 분은 별다른 설명없이도 이 소스를 그냥 가져다가 쓸 수 있습니다.

사용법은 주석으로 간단하게 적어두었습니다. 주의사항도 꼭 확인하시고 사용하시면 됩니다.

개선사항이나 버그가 있다면 댓글 부탁드리겠습니다. ^^

소스는 첨부합니다.


----------------------------------------------
사용법을 문의하시는 분들이 계시네요.  소스도 공개했구 주석처리 다했는데 ^^;;
기본적으로 Notification을 이해하시면 Event도 이해할 수 있습니다. 
그래도 사용하시는데 어려움을 겪으시는 것 같아 간단하게 예제를 들어보지요.

1. 이벤트명 정의 
#define EVENT_WRITE @"eventWrite"

2. 이벤트 발생 
DispatchClass 안에서 아래처럼 코딩합니다.

[[EventCenter defaultCenter]dispatch:self eventName:EVENT_WRITE data:postData];

3. 이벤트 청취 메소드 정의 
ListnerClass 내부에서 아래처럼 정의합니다.

-(void)_myMethod:(Event*)event
{
 PostData *postData = (PostData*)event.data;
 NSLog(@"eventName=%@,  dispatcher=%@",event.eventName, event.dispatcher);
}

4. 이벤트 청취자 등록 
ListenerClass 내부에서 아래처럼 정의합니다. 단 정의시에는 viewDidLoad가 아닌 viewWillAppear나 viewDidAppear등에서 하시는게 메모리 관리가 가능합니다.
[[EventCenter defaultCenter]add:self selector:@selector(_myMethod:) eventName:EVENT_WRITE];

5. 이벤트 청취자 삭제 
ListenerClass 내부에서 아래처럼 정의합니다. 단! dealloc에서는 하지 마세요. 왜냐하면 등록한 listener 내부적으로 retain되기 때문입니다. viewWillAppear등에 add 하셨다면 viewWillDisappear에서 하시면 됩니다. add로 등록하지 않아도 삭제한다고 문제되지 않으니 메모리 관리를 위해서 꼭!!! remove는 호출하셔야 합니다.
[[EventCenter defaultCenter]remove:self selector:@selector(_myMethod) eventName:EVENT_WRITE];

삭제방법은 총 3가지죠. 위 코드는 이벤트에 대한 등록한 청취자 1개만 삭제할때 씁니다. 
하지만 ViewController가 더이상 쓸모가 없어진다면 
[[EventCenter defaultCenter]remove:self] 만 하셔도 self에 정의된 모든 이벤트 청취자를 삭제해줍니다. 



이상입니다. 더 개선할 사항에 대한 아이디어가 있다면 언제든지 답글주세요. ^^

글쓴이 : 지돌스타(http://blog.jidolstar.com/721)
이 블로그를 시작한지도 3~4년이 되어 갑니다. 그동안 Flex, Flash, 천문, 스타플 관련해서 지속적으로 글을 써왔습니다. 지금 돌이켜보면 그렇게 열심히 써왔던 것들이 피가 되고 살이 되어 돌아온다는 것을 너무도 잘 느꼈습니다. 블로그를 통해 온라인에서 다양한 사람들과 교류를 할 수 있었고 미약하게 나마 좋은 사람들도 만나게 되었습니다. 또한 ACC, ACP라는 명함도 달게 되었고요.

이 블로그에는 되도록이면 Adobe 기술에 관련된 것 외에는 담지 않으려고 노력했습니다. 그래서 Flash 관련 내용이 대부분입니다. ACC가 된 이후로는 Adobe 기술에 대한 부분만 집중적으로 올렸었는데, 요즘에는 관련 글이 잘 써지지 않습니다. 왜냐하면 현재 주 업무가 아이폰 개발이다 보니 그렇네요. 그러다보니 블로그가 죽는다는 느낌이 듭니다. 또한 스스로 정리하는 것도 많이 줄어드는 것 같구요.

그래서 이제 좀더 포괄적으로 블로그를 운영하려고 합니다. 제가 최근에 공부하고 느끼는 모든 것을 왠만하면 다 담으려고 합니다.  관련기술, 천문, 스타플에 대한 것만 올리려고 합니다. 제가 좋아하는 드럼과 개인적인 일상 내용은 전부 배제할겁니다.

많은 지식이 있어서 이 블로그를 활용하는 것은 아닙니다. 오히려 너무도 부족함을 느끼기에 블로그를 더욱 쓰고 싶습니다. 지식 욕구를 채우고 또한 좋은 정보도 제공하며 많은 사람들을 만나는 통로를 이 블로그를 통해 만들어 갈 것입니다.
스타플(http://starpl.com)에서 새로운 아이폰 어플, 어플지름신(http://itunes.apple.com/app/id406292683)을 내놓았습니다. 

어플지름신은 아이폰/아이팟터치용 어플의 할인/인기/신상 정보를 거의 실시간 단위로 알려줍니다.
또한 스타플과 연동되어 다양한 어플에 대해서 이야기 할 수 있습니다.

아이폰/아이팟 터치 유저라면 한번쯤 다운로드 받아서 사용해보세요. ^^

어플지름신 앱스토어 URL : http://itunes.apple.com/app/id406292683
어플지름신 이벤트 : http://starpl.com/main/event/view/66
어플지름신 앱스토어 주소 QR Code



어플지름신 스크린 샷








개발후기
이 어플은  제 2번째 작품입니다. 저는 아이폰개발만 맡았고 기획, 프로바이더 서버사이드 개발과 디자인 분야를 맡은 사람이 따로 있지요. 총 개발소요는 설계/코딩/테스트과정 모두 포함해 아주 빠듯하게 2주했고요.  앱스토어에 2주걸려 등록되었네요. 한번 중간에 리젝도 당했고요.

아이폰 어플개발에 손을 댄지 3개월정도 되어가는데 그래도 완성품을 이렇게 만들어가니 기분은 좋습니다. 이제 결과는 지속적으로 지켜봐야겠지요. 앞으로도 이런 유용한 어플을 지속적으로 만들어갈 겁니다. 그래서 오늘도 달립니다. ^^

글쓴이 : 지돌스타(http://blog.jidolstar.com/719)


(2011.07.21)이 글은 조금 오래된 글로 약간 현시점과 다른 내용이 있을 수 있습니다. 현재 Flash Builder는 4.5.1 까지 공식 배포중입니다. Flex 4.5.1 SDK, AIR 2.7도 함께 배포중이므로 참고하세요. 



한동안 아이폰 개발로 Flash 관련된 일을 전혀 하지 못하다 보니 Flash를 주제로 다룬 여기 블로그도 많이 정체되어 있다는 느낌을 지울 수 없더군요. 그래서 시간내서 간단하게 하나 적어봅니다.


지난 몇일전에 미국에서 Adobe MAX가 열렸었죠. 바쁜 나머지 관심있게 지켜보지 못해 주요 주제가 무엇인지는 잘 모르겠지만 여기저기 들리는 것을 보면 결국 "모바일"인 것 같습니다. 이번에 Preview 버전으로 배포된 Flash Builder "Burrito", Flex SDK "Hero", Flash Catalyst "Panini" 모두 모바일 개발에 대한 내용이 추가되었습니다.

저는 이 글에서 Flash Builder를 이용해 Flex나 AIR 어플리케이션을 만들어본 경험이 있는 분들에게 모바일 개발을 아주 쉽게 할 수 있는 일종의 팁을 전달하고자 합니다. 먼저 Flash Builder "Burrito"에 대해서 잠깐 소개하고 Adobe AIR Launchpad를 이용해 어떻게 모바일 AIR 어플리케이션을 만들 수 있는지 소개합니다.


Flash Builder와 Mobile이 만나다. - Flash Builder "Burrito"

Flash Builder "Burrito"에는 Flex SDK "Hero"가 이미 내장되어 있기 때문에 따로 설치할 필요가 없습니다. 여러분은 아래 링크에서 Flash Builder "Burrito"를 다운로드 받을 수 있습니다. 단, Adobe 회원에 먼저 가입하셔야 합니다.

http://labs.adobe.com/technologies/flashbuilder_burrito/

설치는 기존 Flash Builder 4 와 거의 동일합니다. 기존에 설치된 Flash Builder와 별도의 위치에 설치되므로 안심하고 설치하시면 됩니다.

Flash Builder "Burrito"를 실행하시면 먼저 아래와 같은 Start Page가 눈에 띕니다. 이 화면만 보아도 알 수 있듯이 Mobile과 Desktop&Web이 나눠져 있습니다. 여기를 따라 가면 간단한 예제가 있으니 쉽게 따라하실 수 있습니다.



Flash Builder "Burrito"는 아래처럼 모바일 프로젝트를 만들 수 있습니다.


현재는 아래처럼 안드로이드 플렛폼만 지원하고 있습니다. 테스트는 데스크탑에서 가상의 장비를 선택해 시뮬레이션을 할 수 있으며 또한 장비가 있다면 직접 물려서 테스트 해볼 수도 있습니다.


개인적으로 안드로이드 폰(HTC Desire)를 소유하고 있어서 Mobile 버전으로 간단하게 만들어 디바이스 시뮬레이팅을 할 수 있었습니다. 인증서 발급이나 별도의 설정없이 너무 간단하게 만들 수 있어서 기존 Flex 개발자라면 안드로이드용 어플 개발을 쉽게 할 수 있게 되었습니다. 아래 사진이 바로 그 실행결과입니다.



배포도 상당히 간단해서 기존에 AIR 어플리케이션에서 배포버전을 배포하듯이 간단한 인증서 발급만으로 APK로 배포할 수 있습니다.


Adobe AIR Launchpad - AIR 프로젝트 자동화 생성기
Adobe AIR 라운치 패드가 새로 배포되었습니다. 이것은 금방 소개한 Flash Builder "Burrito"를 겨냥해서 제작되었습니다. 이 어플은 Flex개발자들이 데스크탑 및 모바일 AIR 어플을 만드는데 도움을 주기 위한 일정의 자동화 프로젝트 생성기입니다.
 
Flash Builder에서 AIR 프로젝트를 만드는 것은 매우 쉽습니다. 하지만 AIR의 전반적인 기능을 이해해야 제대로된 설정을 할 수 있고 각종 설정은 사실 손이 많이 가는 작업일 수 있습니다. 능숙한 개발자야 문제가 안되지만 초보개발자라면 가이드라인을 제시받고 싶어할 것입니다. 이때 아주 유용할 것 같습니다.

설치하기 위해 다음 링크로 가시면 됩니다.
http://labs.adobe.com/technologies/airlaunchpad/

아래는 실행 첫화면입니다. 프로젝트를 자동으로 생성시켜주기 위한 첫번째 단계로 만들 어플이 데스크탑인지 모바일용인지 선택합니다.

어짜피 데스크탑용이야 많이 해봤으므로 저는 모바일을 선택했습니다. 아래와 같은 화면이 나옵니다. 프로젝트를 생성하기 위해 총 4단계(Setting, Configuration, Samples, Generate)를 거칩니다. 아래 화면은 그중 첫번째 단계지요.

위 화면에서 볼 수 있듯이 어플의 기본 설정을 도와줍니다. Application Name에 어플 이름을 등록하고 버전정보, 풀스크린, 자동회전, 인터넷 엑세스, GPS 등 사용여부를 결정할 수 있고 Icons를 선택하면 사용할 아이콘을 미리 등록할 수 있도록 합니다. 일반 AIR 프로젝트에서는 XML을 직접 편집해야했는데 이런 것을 이용하면 많이 편하겠네요. Install Location은 안드로이드 프로요 버전의 경우 내장 또는 외장(SD카드) 중 둘중에 한곳에 설치할 수 있습니다. 이때 설치 위치를 결정해줍니다. 일반적으로 Auto를 선택하면 되겠네요.

다음으로 아래화면과 같이 Configuration으로 넘어갑니다.  여기서는 소스 코드상에서 각종 핸들링을 지원할 것이냐 결정해줍니다. 필요한 것을 선택하면 원하는 코드가 미리 들어가 있게 됩니다. 참고로 Splash Screen은 실행전에 보여지는 로딩화면으로 생각하시면 됩니다. 여기서 미리 설정할 수 있게 해주네요. 아주 편합니다.
 


이제 아래 화면에서 볼 수 있듯이 Sample로 넘어갑니다. 초보개발자들에게는 이것처럼 좋은게 없겠다는 생각도 듭니다. 아무래도 아무것도 없는 코드보다 샘플이 일단 들어가 주면 개발에 도움이 될 것이기 때문입니다.



마지막으로 Generate 단계입니다. 지금까지 설정한 것을 토대로 AIR 프로젝트를 생성해 줍니다. 먼저 File location에서 프로젝트를 생성할 경로를 설정해줍니다. 그 다음 Generate AIR Project가 활성화 됩니다. 이 버튼을 클릭하면 생성이 완료됩니다. 이때 자동으로 탐색창을 띄워줍니다.


이제 만들어진 프로젝트를 Flash Builder "Burrito"로 열어봅시다. Flash Builder를 실행한 뒤 아래 처럼 File > Import Flash Builder Project를 선택합니다.


아래와 같은 창이 뜨면 만들어진 프로젝트를 여러분의 워크스페이스에 올려놓을 수 있습니다. 창에서 Import Project 를 보면 File과 Project folder를 볼 수 있습니다. Adobe AIR LaunchPad는 프로젝트를 폴더와 압축파일로 두개 만들어주므로 이들중 아무거나 선택해서 프로젝트를 등록하면 별 무리가 없습니다.

여기서는 File을 통해 프로젝트를 임포트 해보지요.


아래처럼 만들어진 프로젝트 압축파일을 선택하면 그 아래에 Import Method가 나옵니다. 여기서 압축된 프로젝트를 어느 곳에 어떤 이름으로 프로젝트를 압축을 풀어 만들 것인가 결정할 수 있습니다. 저는 그냥 Finish 버튼을 눌러 프로젝트를 임포트 하겠습니다.


이제 Flash Builder 에서 해당 프로젝트를 아래 처럼 열람할 수 있게 되었습니다. Adobe AIR LaunchPad를 통해 설정한 대로 프로젝트 명은 TestAIR가 되었고 각종 Sample View가 이미 만들어져 있습니다.


TestAIR 메인 페이지를 열어보았습니다. 아래처럼 mxml 코드를 볼 수 있습니다. 기존 AIR와 달라진 점은 Application이 MobileApplication이라는 점입니다. 당연한 이야기 겠죠? 참고로 firstView가 views.TestAIRHome으로 설정되어 있습니다. 위 패키지에서 views에 들어간 mxml중에 가장 최상위 뷰를 TestAIRHome으로 선택한 다는 것을 의미합니다.

Adobe AIR LaunchPad 의 2번째 단계에서 각종 핸들러를 선택해서 만들어진 코드입니다. 간단하게 trace가 출력되록 되어 있으며 여러분은 필요하다면 이 부분을 수정해서 원하시는 기능을 만드시면 됩니다.

디자인 모드로 들어가 봤습니다. 아래 화면과 같이 모바일에 최적화된 화면을 보여줍니다. Flash builder에서 모바일 어플을 만들 수 있게 된 것이 흥미롭습니다.


위 프로젝트를 실행해보겠습니다. Ctrl+F11 을 누르거나 메뉴에서 Run > Run을 선택해 실행합니다. 그러면 아래와 같은 창이 나오는데 이 화면은 이 글의 초반부에도 보였던 창의 모습입니다. 실행하기 위해 어떤 플랫폼에서 그리고 어떤 디바이스에서 시뮬레이팅을 할 것인지 결정해주는 역할을 합니다. 이 설정화면은 나중에 Run > Run Configurations에서 바꿀 수 있습니다.



위 화면에서 보면 타겟 플랫폼은 안드로이드입니다. 아직까지는 이것밖에 없습니다. 왜냐하면 Flash Builder "Burrito"가 Preview 버전이니깐요. 앞으로 정식버전이 나오면 윈도우, 아이폰 등도 지원하길 희망합니다. ^^

Launch method를 보면 On desktop과 On device가 있습니다. On desktop은 말그대로 데스크탑에서 모바일 시뮬레이터를 띄워줘 테스트 하는 겁니다. 안드로이드를 보니 제가 가지고 있는 HTC Desire도 있어서 기뻤습니다. 반대로 On device는 실제 장비에 물려서 테스트 합니다. 이들 모두 별 설정없이 실행이 가능했습니다. 

이제 Run만 누르면 바로 실행됩니다. 아래는 On device에서 실행해본 것입니다. Adobe AIR LaunchPad를 이용해 등록했던 각종 뷰 종류를 리스트에서 볼 수 있습니다. 마우스로 드래그 하면 아래 있는 나머지 리스트도 볼 수 있습니다. 하지만 데스크탑에서 시뮬레이션 하는 것이므로 Accelerometer나 Multitouch, Gesture등을 수행해 볼 수 없었습니다. 대신 안드로이드 폰이 있는 분은 직접 테스트 해볼 수 있습니다.







저는 제 안드로이드 폰인 HTC Desire에 위 어플을 실행해보고자 합니다. 먼저 메뉴에서 Run > Run Configuration을 선택합니다. 아래 화면처럼 좌측 메뉴에 Mobile Application에서 TestAIR를 선택한뒤 좌측상단에 복사하기 버튼을 누릅니다. 그럼 1개가 더 생성됩니다. 새로 생성된 것은 Name을 TestAIR on Device로 하고 기존것은 TestAIR on Desktop으로 명명합니다. 그리고 새로 생성된 것의 Launch method는 On device를 선택합니다. 그리고 Run을 누르면 자신의 안드로이드 폰에 해당 어플이 실행됩니다.


하지만 여기서 안드로이드 폰이 개발폰이 되도록 먼저 설정해야합니다.
1. 자신의 안드로이드 폰의 홈화면에서 menu > 설정을 누릅니다. 그리고 응용프로그램 > 개발 화면에서 USB 디버깅이 선택되어 있어야 합니다.
2. 자신의 안드로이드 폰에 AIR 런타임이 설치 되어야 합니다. 설치가 안된 안드로이드 폰이면 설치되도록 유도하니 Market에 직접 찾지 않고도 자연스레 설치할 수 있을겁니다.

아래는 제 폰에서 실제로 실행해보는 화면입니다.





정리하며

여기서 설명하지 않은 개발 방법이나 배포 방법에 대한 간단한 가이드는 다음 링크를 참고하면 좋을 것 같습니다.
Flex Test Drive for Mobile - Build a mobile application in an hour 

2009년 미국에서 Adobe MAX 를 참가해 Flash Builder로 아이폰 어플리케이션을 만드는 데모를 본 적이 있습니다. 당시에는 꽤 흥미를 느꼈습니다. 금방이라도 아이폰 어플을 Flash로 개발할 수 있을 줄 알았습니다. 하지만 Apple정책이 변경되면서 퇴색되었죠. 그것도 Flash CS5 런칭 몇일전에 Apple의 이기적인(?) 정책 발표였습니다. 그 후 1년이 지나 안드로이드 플랫폼이 강세가 이어지며 Flash기술은 다시 이야기 거리가 되고 있습니다. Apple도 안드로이드의 강세 행보에 위협을 느껴서(?) 일부 정책 수정있기도 했죠. 어쨌든 Flash가 모바일 디바이스에 자리 잡으려면 아직 해결해야할 과제가 산적해 있지만 그래도 노력한 만큼 성과는 있을 것이라 생각합니다. 


관련글
Flex Test Drive for Mobile - Build a mobile application in an hour
What's new in Flash Builder "Burrito"
Introducing Adobe Flex SDK "Hero"
Mobile development using Adobe Flex SDK "Hero" and Flash Builder "Burrito"
Coding productivity enhancements in Flash Builder "Burrito"

- TV, 모바일 및 PC등 다양한 스크린에서 구동되는 어도비 에어 2.5 출시
- 어도비에서 운영하는 새로운 애플리케이션 스토어, 어도비 인마켓 (Adobe InMarket) 공개

대한민국, 서울 — 2010년 10월 28일 — 한국어도비시스템즈(www.adobe.com/kr, 대표이사 지준영)는 미국 로스앤젤레스에서 10월 24일부터 27일까지 열린, 전세계 개발자와 디자이너들을 위한 컨퍼런스 어도비 맥스(Adobe MAX)에서 TV, 태블릿PC, 스마트폰 및 데스크톱을 아우르는 다양한 스크린에서 웹 브라우저 없이 인터넷 상의 플래시 컨텐츠를 구현하는 애플리케이션 런타임인 어도비 에어 2.5(Adobe® AIR® 2.5)을 발표했다. 어도비 플래시 플랫폼(Adobe Flash® Platform)의 중요 구성요소인 어도비 에어는 개발자들이 기존의 코드를 활용하여 다양한 디바이스와 플랫폼에 적합한 독립형 애플리케이션을 제작하고 전달할 수 있도록 한다.
 
현재 어도비 에어는 윈도우(Windows®), 맥킨토시(Macintosh), 리눅스(Linux®) 운영체제가 탑재된 블랙베리(BlackBerry®) 태블릿 OS, 안드로이드(Android™), iOS, 데스크톱을 기반으로 한 스마트폰과 태블릿PC를 지원한다. 또한, 스마트 TV에 어도비 에어 2.5를 최초로 탑재하는 TV 제조 업체는 삼성전자가 될 것이며, 2010년 후반이나 2011년 초반에 출시되는 에이서(Acer), HTC, 모토로라(Motorola), 림(RIM), 삼성(Samsung) 및 타기업의 태블릿과 스마트폰을 포함한 다양한 디바이스에 어도비 에어 2.5 가 탑재되어 시장에 선보이게 될 예정이다. 어도비 에어를 기반으로 개발자들은 어도비 플래시 프로페셔널 CS5(Adobe® Flash® Professional CS5), 어도비 플래시 빌더(Adobe® Flash® Builder™), 플렉스 (Adobe® Flex™)를 포함한 친숙한 개발 툴들을 활용하여 풍부하고 각 디바이스 환경에 맞는 독립형 애플리케이션을 만들 수 있다.  현재, 많은 애플리케이션이 안드로이드 마켓(Android Market), 인텔 앱업센터(Intel AppUp center), 애플 앱스토어(Apple’s App Store)에 등록되어 있다.
 
어도비 에어 2.5 공개에 이어, 어도비는 개발자들이 온라인 상에서의 에이서, 인텔 및 타 기업의 다양한 디바이스 타입을 넘나들며 그들의 애플리케이션을 사고 팔 수 있는 자체 애플리케이션 스토어인 어도비 인마켓(Adobe InMarket, http://www.adobe.com/devnet/inmarket.html)를 공개하였다. 사용자들은 어도비 인마켓의 스토어프론트에서 직접 애플리케이션을 다운로드 받을 수 있다. 
 
어도비 크리에이티브 및 인터랙티브 솔루션 사업부의 데이비드 와드화니(David Wadhwani) 수석 부사장은  “ 어도비 에어 2.5의 발표로 3백만 명 이상의 플래시 개발자들이 다양한 애플리케이션 스토어 및 디바이스를 넘나들며 쉽게 게임 및 애플리케이션을 개발하고 운영할 수 있게 되었다.”라고 말하며, “이는 풍부하고 혁신적인 애플리케이션을 제공하고자 하는 개발자들과, 개별 디바이스 및 플랫폼을 구축할 때 발생되었던 비용을 절감하고자 하는 이들에게 큰 도움이 될 것으로 기대된다.”라고 말했다.
 
에어 2.5는 가속계, 카메라, 비디오, 마이크, 멀티 터치 및 동작감지를 포함한 다양한 새로운 기능들을 통해 풍부한 애플리케이션 사용자경험의 기반을 제공한다. 위치 정보 기능은 개발자들이 위치 기반의 애플리케이션 서비스를 제공할 수 있도록 한다. 또한, 에어 2.5는 HTML5와 플래시(확장자 .SWF) 컨텐츠를 통합함으로써 애플리케이션 내에 네이티브 브라우저 컨트롤(native browser control)을 보여줄 수 있으며, SQLite 을 지원하여 에어 애플리케이션 내에 데이터베이스를 쉽게 저장할 수 있다. 또한, 브로드컴社(Broadcom Corporation), 인텔社, 엔비디아社, ST마이크로일렉트로닉스社, 트리던트社 (Trident), 텍사스 인스트루먼츠社(Texas Instruments), 퀼컴社(Qualcomm) 등을 포함한 주요 반도체 기업 들의 제품에서 어도비 에어를 위한 하드웨어 가속화를 지원한다.
 
어도비 플래시 플레이어 10.1 (Adobe® Flash® Player 10.1)
안드로이드 마켓에서 5만 여 명 이상이 5개 만점에서 별 4.5개의 평가로 이미 무료 인기 애플리케이션 중 하나가 된 플래시 플레이어 10.1은 모바일 디바이스 상에서 브라우저를 통한 풍부한 플래시 컨텐츠를 구동시키는 런타임이다.  현재, 어도비 런타임은 12 종류의 안드로이드 디바이스에서 구동되고 있으며, 앞으로 더 많은 안드로이드 디바이스에 구동 될 예정이다. 또한, 공식적으로 안드로이드 마켓에서 플래시 플레이어 10.1이 2백 만 번 이상이 다운로드 되었다고 발표된 바 있다.
모바일 용 런타임은 안드로이드 마켓에서 디바이스 제조업체 따라 배포되며, 이미 설치한 운영자와 운영시스템에 의해 업그레이드 된다. 플래시 플레이어 10.1은 현재 안드로이드와 구글 TV에서 이용가능하며, 앞으로 블랙베리 플랫폼, HP 웹 OS 2.0, 윈도우(Windows®)폰 차기 버전, 리모(LiMo), 미고(MeeGo) 및 심비안 OS 에서도 지원될 계획이다. 플래시 플레이어 10.1이 지원되는 디바이스는 어도비 웹페이지(http://www.adobe.com/flashplatform/supported_devices/smartphones.html)에서 확인 할 수 있다.
 
플래시 플랫폼 개발 툴
어도비는 멀티스크린 상에서의 개발 과정을 보다 간소화 시켜주는 개발자 툴 베타버전을 발표했다. 어도비 에어 2.5 소프트웨어 개발 키트(SDK)를 포함한 새로운 플래시 플랫폼 툴의 출시로, 개발자들은 디자인과 개발 생산성을 극대화시키면서 스마트폰, 태블릿 및 TV 용 모바일과 멀티스크린 애플리케이션을 구축할 수 있다. 플렉스 프레임워크의 오픈소스 업데이트는 개발자들에게 웹, 데스크톱, 그리고 현재 모바일 애플리케이션을 위한 광범위한 프레임워크를 제공한다. 개발자들은 웹과 데스크톱의 플랫폼상에서와 같이, 손쉽게 고품질의 모바일 플렉스 애플리케이션을 구축할 수 있다. 더 자세한 사항은 어도비 웹페이지(http://www.adobe.com/go/flexsdk_preview/)에서 확인할 수 있다.
 
어도비 플래시 빌더 베타버전은 개발자들의 개발 비용을 절감시키며, 익숙한 개발언어와 구성요소, 툴을 활용하여 멀티스크린을 위한 애플리케이션을 구축할 수 있도록 한다. 특히, 모바일 디바이스로의 확장과 디바이스상에서의 디버깅, 빠른 개발을 위한 코딩 툴들의 매우 놀랍고 새로운 기능들이 플렉스 등에 추가 되었다.
 
이용 방법
윈도우, 맥킨토시, 리눅스가 탑재된 안드로이드 및 데스크톱 OS 용 어도비 에어 2.5 와 어도비 에어 2.5 SDK는 현재 이용 가능하다 .어도비 에어를 위한 블랙베리 태블릿 OS SDK는 블랙베리 태블릿 OS용 애플리케이션을 제작하기 위해 어도비 에어 2.5 SDK와 함께 작동하는 것으로 림(RIM)에서 이용 가능하며 이것은 블랙베리 플레이북에 미리 탑재될 예정이다.


------------------------------------------------------------------------------
회사일이 너무 바뻐서 Adobe MAX 2010 행사에는 관심을 가지기가 힘들었네요.

작년 맥스 행사에서 Open Screen Project 일환으로 다양한 모바일 기기로 Flash 기술이 도입되는 시점이였다면 이제 본격적인 진입시점에 도달한 것 같습니다. 실제로 국내에도 스마트폰이 엄청나게 보급되어가고 있으니깐요. 이번 AIR 2.5도 이런 차원에서 모든 것이 진행된 것을 판단합니다. ACC분들의 생생한 Max 중계를 다음 링크에서 확인할 수 있습니다.

http://twitter.com/#!/search?q=%23atMAX2010
http://www.action-scripter.com/blog/search/Adobe%20Max%202010
http://twitter.com/#!/FlashLovesMe
http://me2day.net/lovedev
http://koko8829.tistory.com/tag/Max%202010

그외 소식
Adobe MAX 2010
MAX Online
어도비, 모바일로 진화
11월 13일, 모바일+플래시 개발자를 위한 즐거운 수다
12월 7일, FITC Seoul 2010
삼성 스마트TV에 어도비 AIR 탑재된다
Introducing the Molehill 3D APIs
타임라인으로HTML5컨텐츠 작성을 가능하게 한다---Adobe MAX 2010기조 강연
Adobe 앱 Air 2.5, 스마트폰, 태블릿, TV 모두 같은 앱을 사용한다?!
어도비 AIR 2.5, RIM 플레이북 앱 개발로 확산 시동 
Adobe AIR features
3D APIs for Adobe Flash Player and Adobe AIR
Adobe Flash Builder "Burrito"
Flash Player features

스타플 모바일 웹사이트(http://m.starpl.com)에 이어 어플리케이션도 오픈했습니다.


아이폰, 아이팟터치, 안드로이드폰을 가지고 계신 분들은 스타플 모바일 어플리케이션을 설치하실 수 있습니다.

 

다음 링크에서 다운로드 받으세요.

- 아이폰/아이팟터치 사용자
  한국 : http://itunes.apple.com/kr/app/id396402081?mt=8
  미국 : http://itunes.apple.com/us/app/id396402081?mt=8


- 안드로이드폰(디자이어,넥서스원,겔럭시 S등) 사용자 
  http://www.cyrket.com/p/android/com.starpl.android/


자세한 설명 보기 : http://starpl.com/wecon/11357889


아이폰 스크린샷 






안드로이드 스크린 샷 




글쓴이 : 지돌스타(http://blog.jidolstar.com)


한국 Adobe에서 Flash Platform 웹 접근성 세미나가 10월 7일 강남 교보타워 23층 이벤트홀에서 진행할 예정입니다.

요즘 장애인들도 웹에 쉽게 접근할 수 있도록 기술적, 정책적 이슈가 많이 대두되고 있습니다. 어도비에서도 관련 문제에 대해서 인식하고 있으며 이 이슈를 처리해야할 다양한 대안을 마련하고 있습니다.

흔히들 Flash는 웹 접근성과는 별개라고 생각합니다. 물론 예전에는 그랬죠. 하지만 Flash Player가 진보하면서 접근성에 관련된 API도 추가된 것을 볼 수 있듯이 이 부분에 대한 다양한 노력이 있는 것 같습니다.

예상컨데 앞으로 웹접근성은 선택이 아닌 필수가 될 것이며 웹환경이 장애인과 비장애인간을 차별하지 못하도록 법제화가 될 것입니다. 이번 세미나를 통해 미리미리 준비한다면 그것 또한 큰 경쟁력이 될 것입니다.

자세한 사항 및 등록은 아래 링크를 참고하시길 바랍니다.

http://www.adobeflex.co.kr/iwt/board/board.php?tn=news&id=341&mode=view

스타플 모바일 버전으로 웹페이지를 오픈했습니다. 

http://starpl.com/m

기존 스타플의 내용을 거의 그대로 담겨 있고 모바일의 작은 화면서 사용하기 편하도록 구성되었습니다. 

기본적으로 아이폰, 안드로이드폰의 웹브라우져에서 잘 동작합니다. 아래는 스타플 모바일의 스크린 샷입니다.

스타플 모바일의 메뉴화면

스타플 모바일에서 나의 관심사들


스타플 모바일에서 관심사 "스타크래프트"에 글이 리스팅된 모습

스타플 모바일의 한줄쓰기


안드로이드폰(hTC 디자이어)에서 스타플 모바일 접속 모습

아이폰 3GS에서 스타플 모바일 접속 모습

안드로이드 및 아이폰용 어플리케이션도 제작중에 있습니다. 그럼 즐거운 추석 보내세요.

글쓴이 : 지돌스타(http://blog.jidolstar.com/713)

얼마전 hTC 디자이어 안드로이드 스마트폰을 구입했다. 스마트 폰에는 항상 관심이 많았으나 정작 구입하려고 하니 아이폰으로 할지 안드로이드로 할지 선택의 기로에 서게 되었다. 결국 안드로이드 선택... 왜냐하면 아이폰, 아이팟 터치 계열을 회사에서 너무도 많이 봤고 개발용으로는 하나 이미 장만한 터였다.



Flash 개발자로서 안드로이드 2.2 프로요에 관심을 안가질 수 없었다. 오픈 스크린 프로젝트(Open Screen Project)의 일환으로 만들어진 Flash Player 10.1이 안드로이드 2.2 프로요에 탑재되기 시작했기 때문이다. 본인이 구입한 hTC 디자이어 폰은 2.1이 설치되어 있었지만 hTC에서 2.2 업그레이드 버전을 내놓았기 때문에 어렵지 않게 설치할 수 있었다.

안드로이드 2.2 프로요에 탑재된 Flash Player 10.1을 테스트 하기 위해 필자가 만들었던 몇가지 Flash 애플리케이션에 접속해 보았다.

아래는 실험적으로 만들어본 3D 태양계 시뮬레이터를 Papervision3D로 만든 것이다. 아래 주소로 접속할 수 있다.  마우스 드래그로 회전이 되고 방향키로 확대/축소 할 수 있다.
http://weconize.com/~blackhole/planet3d (임시 링크이다)


 

Papervision3D는 Flash Player 10부터 지원하는 3D API를 전혀 사용하지 않았다. 그럼에도 불구하고 동작하는 것을 보면 신기하다. 3D API를 적극적으로 활용한 Away3DAlternativa 3D로 만들면 훨씬 부드러운 화면을 보여줄 수 있을 것이라 판단한다.

스타플(http://starpl.com/)의 별지도(http://starpl.com/map) 에 접속해보았다.


위 화면은 hTC 디자이어, 안드로이드 2.2 프로요에서 스타플 별지도에 접속해본 모습이다.



위 화면은 웹브라우져로 본 스타플 별지도와 hTC 디자이어로 본 별지도 모습을 비교해 보았다.


 

위 동영상에서 볼 수 있듯이 부자연스럽긴 하지만 Flash 로 만들어진 별지도가 잘 동작하고 있다. 단지 웹기반으로 만들어서 버튼이 너무 작아 누르기가 불편했으며 마우스 이벤트와 터치 이벤트는 명백히 다르기 때문에 동작에 무리가 빠른다. 이런 불편함을 해소하기 위해서는 모바일을 감안한 Flash 애플리케이션을 만들어야 함을 알 수 있다.

아래 화면은 2010 남아공 월드컵을 위해 만들었던 Flash 축구 게임이다. 실행이 잘된다. 또한 사운드도 잘나왔다. 하지만 마우스 이벤트 기반으로 만들었기 때문에 터치에 대응하지 않아 실제 게임은 불가능했다. 데스크탑에서 마우스 사용과 모바일에서 터치는 엄연히 다른 사용자 반응이므로 모바일에서도 동작시키려면 그에 맞게 개발해야함을 알 수 있다.

월드컵 게임 : http://weconize.com/~blackhole/worldcup (임시링크이다.)



필자 블로그(http://blog.jidolstar.com)에 Flex 시절부터 인연이 있으신 분들은 아마도 Flex 한글화 문서(http://flexdocs.kr)를 잘 알고 있을 것이다.  여기서 제공하는 3D 게시판(http://flexdocs.kr/board)도 동작시켜보았다.




위 동영상에서 볼 수 있듯이 Flex 애플리케이션도 문제없이 돌아간다. 단지 데스크탑용이기 때문에 모바일 용에도 대응할 수 있도록 만들어야 하는 문제는 있다.


마지막으로 유명한 Flash 3D 라이브러리인 Alternativa 3D 에서 제공하는 Demo를 보고자 한다.

접속 URL : http://blog.alternativaplatform.com/en/category/3d/

 

위 동영상에서는 블로그 위에 있는 Flash 컨텐츠를 바로 스마트폰에서 볼 수 있음을 알 수 있다. 중간에 Youtube 동영상도 잘 동작한다. 참고로 동영상에 게임은 Flash로 만든 온라인 탱크 게임이다. Flash의 멀티터치 API를 이용해 게임을 즐기는 것도 가능해 짐을 보여준다. 또한 Alternativa 3D 라이브러리를 이용해 제작된 3D Flash 데모를 보여준다. 모바일 수준에서 Flash가 이런 렌더링 능력을 보여준다는 것이 대단할 따름이다. 

 

오픈 스크린 프로젝트란?
오픈 스크린 프로젝트의 슬로건은 'Singular Experience, multiple Devices'이다. 간단히 말해 웹에서 플래시를 통해 얻었던 사용자 경험을 휴대폰, 텔레비전, 그리고 다양한 전자기기에서도 동일하게 느끼도록 한다. 그러기 위해 Adobe는 자신의 스펙 및 기술적 정보를 공유하고 관련 기기업체도 이에 맞게 지원하여 서로 윈윈(Win-win)하는 프로젝트이다. 이번 구글의 안드로이드 2.2 프로요에 Flash Player 10.1가 기본 탑재된 것은 바로 이 프로젝트의 성과물이라고 할 수 있다.



오픈 스크린 프로젝트 공식 홈페이지
미국 LA Adobe MAX 2009 - 오픈 스크린 프로젝트와 플래시 플랫폼 서비스에 대해
PC-모바일 넘어 디지털 가전까지 확장
어도비-엔비디아, 플래시 플레이어 GPU 가속 협력 발표
어도비의 야심작, 오픈 스크린 프로젝트
안드로이드에서 동작하는 Flash Player 10.1 영상

 

정리하며
어도비가 Flash를 다양한 디바이스에서 동작시키기 위해 오픈 스크린 프로젝트를 진행했고 이제 그 결과물을 우리는 하나씩 볼 수 있게 되었다. 

하지만 방금 보여줬던 몇가지 동영상을 보더라도 데스크탑에서 동작하는 Flash 애플리케이션은 모바일에서 사용하기에는 너무 불편한 것은 사실이다.  그래서 디바이스의 특징(가령 데스크탑과 모바일)에 따라 Flash Player 10.1에서 제공하는 터치 및 가속센싱과 같은 API를 활용하여 사용자 경험을 극대화 하기 위한 개발자의 노력이 필요하게 되었다. 그럼에도 불구하고 개발의 약간의 불편함을 제외하고는 기존에 만들어놓은 Flash 컨텐츠를 거의 그대로 사용할 수 있다는 점은 큰 장점이 아닐 수 없다.

Flash Player 10.1 부터 제공하는 새로운 기능은 다음 링크를 참고하면 되겠다.
http://www.adobe.com/products/flashplayer/features/


최근 Apple의 정책 변경에 따라 Flash, AIR를 이용한 앱 개발에 물꼬를 틀 것으로 보인다. Adobe 기술을 이용해 이제는 아이폰, 아이패드와 같은 장치에도 애플리케이션을 배포할 수 있게 된 것이다. 사용자는 기존 다양한 Flash 컨텐츠가 안드로이드 계열의 디바이스 뿐 아니라 iOS 기반에도 탑재가 가능해짐으로써 기존 Flash 컨텐츠를 경험할 수 있는 기회가 더욱 많아졌다.


글쓴이 : 지돌스타(http:/blog.jidolstar.com/712)

이글은 Adobe RIA 공식 사이트에도 소개 되었습니다.
http://adoberia.co.kr/iwt/blog/blog.php?tn=flex&id=546


Flash Platform 커뮤니티인 플래시 액션스크립트 카페가 주최하는 제7회 플래시 액션스크립트 커뮤니티 컨퍼런스가 9 11일에 개최됩니다.

 

세미나 정보

§ 일시: 2010 9 11일 토요일 (오후 12 ~ 5)

§ 장소: 역삼동 GS타워 25층 대강당 [약도보기]

 

세미나 신청 방법

§ 인원: 선착순 100

§ 참가비: 5,000

§ 참가방법: 본 글에 댓글 등록(순번/이름/ID 입력) à 참가비 입금 à 입금 확인 à 등록 완료

§ 입금계좌: 카페매니저 강성규 / 우리은행 / 590-099329-02-101 (입금자명과 등록자명이 동일해야 합니다)

 

AGENDA

시간

내용

발표자

12:20 ~ 13:00

등록

13:00 ~ 13:50

알면 도움되는 참조이야기

허남진(허수아비)

14:00 ~ 14:50

대화하는 코드

강동혁(동강)

15:00 ~ 15:50

아크로버스 AR(Augmented Rreality)

정해윤 팀장

16:00 ~ 16:50

Flash and Social Network Game

윤진상(우야꼬)

16:50 ~ 17:00

맺음말

       

출처 : http://adoberia.co.kr/iwt/blog/blog.php?tn=flex&id=541

+ Recent posts