아이폰어플개발정보2010. 8. 13. 14:26
IBOulet 없이 델리게이트 구현하는 간단한 방법

출처 : http://cafe.naver.com/mcbugi.cafe?iframe_url=/ArticleRead.nhn%3Fclubid=16914752%26page=21%26searchtype=1%26query=delegate%26searchdate=all%26articlemedia=0%26sortby=date%26articleid=7177%26referrerAllArticles=true

이번 강좌에서 델리게이트 이론을 이해하실수 있도록 도와드리기 위해 델리게이트 구현법을 설명하겠습니다

"IB 없이 하기, UITableView끝장보기 (1) 델리게이트 구현이론"편에서 (http://cafe.naver.com/mcbugi/6676)

이미 감 잡으신 분도 있겠지만

그래도 이해 못하신 분들을 위해 설명해 보겠습니다.

아마 많은 분들이 고민하셨을거라 봅니다.

바로 객체간 데이터 통신입니다

예를 들어 객체 A와 B가 있습니다

A가 B에 데이터를 보내거나 함수를 호출하는건

A가 B를 하위로 소유하고 참조함으로서 간단히 B에 접근이 가능합니다 

그리고 B가 A를 호출 하려면 B에 A의 주소가 입력되어 있고 A를 참조해야지만 접근이 가능합니다

결국 A가 B를 쓰려면 B를 참조하는걸로 가능하지만 B가 A를 호출하려면 B가 A를 참조해야 합니다

좀 헤깔리나요;;;

결론은 A와 B가 서로 통신하려면 서로 참조해야 한다는 겁니다.

하지만 만약

A가 만든 ViewController이고 B가 UITableView이라면 서로 참조하는 방식은 불가능합니다

UITableView는 제공되는 API라서 UITableView의 헤더를 수정한다는건 불가능하기 때문이죠.

그래서 사용된것이 델리게이트 프로토콜 방법입니다

약속된 함수만 호출 하도록 하는거죠

하지만 여태껏 API에서 정의된 델리게이트만 사용해보고

직접 그쪽에서 어떻게 호출하는지 알수가 없습니다

즉 있는걸 써보기만 했습니다

그래서 이번에는 직접 델리게이트를 구현해보겠습니다

한번 간단한 게임을 만들어 보겠습니다

뭐가좋을까요.....

아 폭탄 해체 게임을 해보도록 하겠습니다.

우선 Window-Based로 새 프로젝트는 만듭니다

프로젝트명은 Boom이라 하죠

간단한 어플이 될것이니 ViewController까지 만들것 없이 뷰만 가지고 만들어 보겠습니다

뷰를 하나 만들고 시간 카운트 폭탄이 될것이니 

빨간선, 파랑선 버튼 두개 만들고 시간을 표시할 라벨뷰 

이렇게 세개의 뷰를 만듭니다

어플의 시작 위치인 AppDelegate에서 만든 BoomView를 넣어줍니다

BoomView입니다 우선 아무것도 없습니다


 lblTime만 만든 이유는 이 컨트롤만 나중에 계속 접근할 필요가 있기 때문입니다 (시간 표시)

init함수에서 lblTime과 두 번튼을 만들겠습니다

그리고 각각의 버튼이 눌러졌을때 각각 Red와 Blue함수가 호출되도록 했습니다

BoomView를 더 구현하기 전에 먼저 폭탄을 만들어야 겠죠

Bomb클래스를 NSObject로 만듭니다

정말 아무것도 없습니다.

우선 클래스의 구조를 구현하겠습니다

객체가 만들어지면 타이머를 설정하고 시간다 되면 폭파 시키겠습니다

우선 헤더에 다음 코드를 넣습니다

NSTimer *myTimer;

int timeCount;

@property 설정은 필요없습니다 안에서만 다룰거라


그리고 클래스 구현 파일에서 다음 코드를 넣습니다

- (id)init {

self = [superinit];
if (self != nil) {
timeCount = 10;
myTimer = [NSTimerscheduledTimerWithTimeInterval:1.0target:selfselector:@selector(chkTime) userInfo:nilrepeats:YES];
}
returnself;

}

- (void)chkTime {

timeCount--;
if (timeCount == 0) {
[myTimer invalidate];
myTimer = nil;

//
}

}


우선 timeCount를 10주고 시작합니다

그리고 매초마다 chkTime이 실행 되도록 설정했습니다

매초 실행 할때마다 카운트가 줄고 0이 되면 타이머는 끄도록 했습니다


그러고보니 어떤 선이 맞는건지 정하는걸 깜빡했군요


헤더에 Bomb 클래스 선언 전에 다음코드를 넣습니다

enum {

    BombLineRed = 0,

    BombLineBlue = 1,

};

typedef NSUInteger BombLineColor; 


이것은 int값과 같은것이지만 알아보기 쉽도록 했습니다

그리고 클래스 변수로 선언합니다

BombLineColor RightLine;



그리고 선을 자를때 호출되는 함수도 필요합니다

- (void)CutColor:(BombLineColor)Color;




 그리고 Bomb.m에서

초기화 함수 (init)에 아래 코드를 넣습니다

srandom(time(NULL));

RightLine = random() % 2;


 

그리고 새로운 함수를 추가합니다

- (void)CutColor:(BombLineColor)Color {

if (Color == RightLine) {
else {
}

}


맞을경우와 틀릴경우입니다만


아직 델리게이트 구현을 안했으므로 나중에 수정하겠습니다




여기서 잠시 정리해 보겠습니다

Bomb객체가 만들어지면 (init)

남은시간은 10초가 되고 (timeCount)

어느 선을 잘라야 폭탄이 멈추는지 설정합니다 (RightLine)

그리고 타이머가 작동합니다 (myTimer)


시간이 다 지나면 터질것이고 잘못 잘라도 터질것입니다

선을 자를때는 - (void)CutColor:(BombLineColor)Color;를 호출합니다





이제 본격적으로 델리게이트 구현을 해보겠습니다

 먼저 헤더에서

@protocol BombDelegate; 선언을 합니다

그리고

클래스 변수로 

id delegate;

를 선언합니다


이건 외부에서도 접근해야 하니 당연히 property선언이 되어 있어야 합니다

@property (nonatomic,assignid delegate;





헤더의 맨 밑에 다음 코드를 추가 합니다

@protocol BombDelegate<NSObject>

@end

아까 위에서 추가한것은 미리 정의한것으로 보시면 됩니다


이제 델리게이트가 호출할 함수들을 정의하면 됩니다


여기서 필요한것은


폭탄이 멈추거나 터졌을때 호출되는 함수와


매초 줄때마다 호출되는 카운트 함수, 이 두개가 필요 하겠군요

- (void)BombTimeCount:(int)count;

먼저 타임 카운트 입니다 간단히 몇초 남았나 count에 인자로 돌려줍니다

- (void)BombResponse:(Bomb *)Object Response:(BombResponseType)Response;

폭탄이 터지거나 멈출경우 호출되는 함수로 위와 같이 만들었습니다

Object 인자로 이 폭탄 객체의 주소를 돌려줍니다

Response는 터졌거나 멈췄거나 둘중 하나 입니다만

BombResponseType또한 BombLineColor처럼 int타입으로  정의했습니다

헤더 상단에 아래 코드를 넣어 줍니다

enum {

BombStoped = 1,
BombBoom = 2,

};

typedef NSUInteger BombResponseType;

그냥 0, 1 식으로 해도 상관없으나 기왕이면 알아보기 쉽게 하겠습니다


델리게이트 구현할때 특징중 하나가


반드시 필요한 함수와 있어도 되는 함수를 정의 할수 있다는겁니다



현재 사용할 함수는 위의 두개 입니다


그러나 남은 시간을 안보고 그냥 선을 자를수도 있습니다



그래서 BombTimeCount함수는 옵션으로 설정합니다


그래서 코딩하면...



다음과 같이 됩니다

@required가 반드시 정의될 함수들이고

@optional이 필수는 아닌 함수들입니다

헤더 정의는 끝났으니  Bomb.m을 수정해 보겠습니다


아까 헤더에서 delegate가 @property로 설정되었으니

@synthesize delegate; 코드를 넣어줍니다

우선 chkTime함수부터 고쳐 보겠습니다

먼저 초가 하나 줄면

BombTimeCount를 호출해서 알려줍니다


그래서 다음 코드를  timeCount--;다음에 넣어줍니다

[self.delegateBombTimeCount:timeCount];


하지면 여기서 문제가 있습니다

아까한 약속은 BombTimeCount함수가 필수가 아닌 @optional이라는 겁니다

그래서 상대 객체에서 이 함수를 구현을 안했을수도 있습니다


@optional으로 정의 했다고 컴파일러에서 알아서 해주는것이 아니기 때문에


구현이 안되었을 경우를 상정해서 코드를 적어야 합니다

상대 객체에 구현되었는지 확인하는 코드는 다음과 같습니다

[self.delegaterespondsToSelector:@selector(BombTimeCount:)]

여기서 주의하실점은 인자입니다


예를 들어

함수가 

- (void)test; 라면 @selector(test)

- (void)test:(int)a; 라면 @selector(test:)

- (void)test:(int)a b:(int)b; 라면 @selector(test:b:)
- (void)test:(int)a b:(BOOL)b c:(NSString *)c d:(NSNumber *)d e:(UIImage *)e  라면 @selector(test:b:c:d:e:)


가됩니다


인자와 마춰주지 않으면 문제가 됩니다


그래서 맞는 코드는 다음과 같습니다

if ([self.delegaterespondsToSelector:@selector(BombTimeCount:)] ) {

[self.delegateBombTimeCount:timeCount];

}


이제 시간이 0초일때 폭탄이 터지니

다음 코드를 그if문 사이에 넣어줍니다

[self.delegateBombResponse:selfResponse:BombBoom];


BombResponse의 경우 @required로 정의 하였으니 별도로 구현을 확인할 필요가 없습니다.


시간 카운트 쪽은 끝났습니다


이번에는 선을 잘랐을때 입니다


기존의 코드를 다음과 같이 수정합니다

- (void)CutColor:(BombLineColor)Color {

[myTimerinvalidate];
myTimer = nil;
if (Color == RightLine) {
[self.delegateBombResponse:selfResponse:BombStoped];
else {
[self.delegateBombResponse:selfResponse:BombBoom];
}

}


선을 자를때 타이머를 꺼줍니다 (어차피 자르면 둘중하나이니,,,)



이제 Bomb 객체구현은 끝났습니다


이제 BoomView에서 사용해 보겠습니다


먼저 객체를 참조하고 델리게이트 약속을 합니다


BoomView.h에서

#import "Bomb.h"

정의해줍니다


그리고 BoomView헤더를 다음과 같이 수정해서 프로토콜 약속을 합니다

@interface BoomView : UIView {

클래스 변수로 

Bomb *bomb;선언을 합니다

이제 BoomView.m에서


init(초기화) 함수에서 폭탄을 할당하고 초기화 합니다

bomb = [[Bomb allocinit];
bomb.delegate = self; 


그리고 아까 만든 약속한 함수 두개를 구현해 줍니다

- (void)BombResponse:(Bomb *)Object Response:(BombResponseType)Response {

if (Response == BombBoom) {
UIAlertView *alert = [[UIAlertViewallocinitWithTitle:@"Boom!"message:nildelegate:nilcancelButtonTitle:@""otherButtonTitles:nil];
[alert show];
[alert release];
else {
UIAlertView *alert = [[UIAlertViewallocinitWithTitle:@"해제됨"message:nildelegate:nilcancelButtonTitle:@""otherButtonTitles:nil];
[alert show];
[alert release];
}

}

- (void)BombTimeCount:(int)count {

lblTime.text = [NSStringstringWithFormat:@"남은시간 : %i",count];

}

폭탄이 어떻게 되냐에 따라 뜨는 메세지가 다르도록 했습니다


이번에는 선 자르는 코드입니다


아까 구현한 두 함수가 Red와Blue였습니다 그걸 다음과 같이 수정해줍니다

- (void)Red {

[bombCutColor:BombLineRed];

}

- (void)Blue {

[bombCutColor:BombLineBlue];

}


완성된 코드


이상으로 델리게이트 구현법을 마치겠습니다

여기까지 읽어 주셔서 감사합니다 ^^



출처 : http://blog.naver.com/PostView.nhn?blogId=74hans&logNo=110226436
Posted by 오늘마감

댓글을 달아 주세요