개인적으로 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


+ Recent posts