목차

델리게이트에 대해서

일명 도우미 객체로서, 책에서는 이렇게 비유를 했다.

로보캅의 경우, 사람의 서브클래스를 만들어 수십명의 외과의 공학자가 붙어서 사람을 전투머신으로 확장하여 로보캅이 완성되었다. → 현재의 많은 프레임워크가 이 방식을 쓰고 있다.

전격Z작전에서 마이클의 서브클래스를 만들어 총,자동차,로켓을 추가해서 모든 것을 재정의 하려고 했지만, 마이클에 많은 것을 알아야 장착이 가능했다. 그렇게 하는 것보다 키트를 만들어서, 도우미 객체로서 마이클에게 지급하고 마이클이 사용하도록 했다.

코코아에서는 재사용이 필요한 객체에 대해서, 상속 받아서 확장하는 것보다는
도우미 객체를 줘버려서 필요 없는 확장을 하지 않고도 기능 확장이 가능하도록 구성되어 있다.

C# 에도 있다는데, 잘 모르겠는데..

다음과 같은 경우,

이런 인터페이스 상의 이벤트를 받아서 처리하고 싶을 때,
NSWindows 를 상속 받아서 새로운 NSMyNewWindow를 만들 것이 아니라

NSWindows에 선언던 델리게이트 함수를, 이벤트가 발생되었을때 자동으로 불리게 되는 함수들을
연결해서 쓸 수 있게 되면 더 간단하게 이벤트를 캐치해서 작성 할 수 있다.

델리게이트는 어떻게 설정하나?

두 객체가 있다.

인터페이스 빌드 상에서

스크린샷을 나중에 추가

  1. 발생하는 이벤트를 처리하고 싶은 UI컨트롤(A)에서 마우스 R-Click
  2. Outlets 그룹에서 delegate 항목을 클릭한 상태로
  3. Controller 클래스, 아니면 도우미 객체로서 이벤트를 받아서 처리해 줬으면 하는 클래스(B)
  4. 로 마우스를 드래그한다.

델리게이트 관계 설정은 이것으로 완료.

코딩으로

이 방법 깔끔하게 안됨 . 뭔가 빠져 있는듯.

코딩으로 처리하기 위해서는, A 의 아웃렛 변수가 B 에 선언되어 있어야 한다.
또는,
B가 어디가에는 변수로 선언되어 있어야 한다.

[B setDeletgate:self]

또는

[B setDelegate:someObject]

로 코드를 추가한다.

델리게이트는 어떻게 쓰는건가?

A Controller 에서 B window 의 델리게이트를 처리하고 싶다면,

A에 B의 델리게이트 메소드를 자신의 메소드인냥 추가시키면 된다.

AppController 클래스가 NSWindow의 도우미객체로(델리게이트설정이) 되어 있고
NSWindow의 윈도우의 크기가 바뀔 때마다 크기를 강제로 설정해버리는 말도 안되는 예제를
구현한다고 했을때

// declare AppController
 
#import <Cocoa/Cocoa.h>
 
@interface AppController : NSObject 
{
    // IBOutlet NSWindow* mainWindow;
}
- (id) init;
// windowWillResize 는 NSWindow의 델리게이트 함수입니다
- (NSSize) windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize;
@end
 
@implementation AppController
 
- (id) init
{
    if( ![super init] ) return nil;
    // NSWindow의 델리게이트 기능을 수동을 설정
    //[mainWindow setDelegate:self];
    return self;
}
 
// 윈도우가 리사이즈 될때마다 이 함수가 불려서 윈도우 크기를 강제로 (500,100)으로 설정해버립니다.
- (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
{
    NSSize _mySize;
    _mySize.width = 500.0;
    _mySize.height  = 100.0;
 
    NSLog( @"windowWillResize called" );
 
    return _mySize;
}
 
@end

델리게이트는 어떻게 동작하는 건가?

NSObject에서 상속된 모든 클래스는

  1. (BOOL) respondsToSelector:(SEL)aSelector

이 메소드를 갖고 있다.

델리게이트용 클래스가 세팅 되어 있는 경우에는 (위 함수의 리턴값이 참이면) 델리게이트함수의 메소드를 부르고 없으면 원래의 메소드 내용을 실행하도록 되어 있다. (고 한다.. 정말인지 확인해보면 좋을 듯)

델리게이트를 거쳐 가는지 확인해보고 싶다면,

- (BOOL) respondsToSelector:(SEL)aSelector
{
    NSString *methodName = NSStringFromSelector(aSelector);
    NSLog( @"repondsToSelector:%@", methodName );
    return [super respondsToSelector:aSelector];
}

로그를 남겨서 확인해보라.

cocoa