Notification (통보) 사용하기

개발 & SDK 2009/06/08 01:08

통보는 하나 이상의 객체가 어떤 이벤트를 받고 싶을때 사용한다. 델리게이트가 1:1 관계로 객체간에 긴밀하게 연결되어 있다면, 통보 서비스는 동적으로 임의적인 객체간의 연결이 가능하다.

어떤 객체가 관심 있는 이벤트에 대해서 통보를 받기 위해서는 통보 센터에 자신을 등록해야 한다. 다음 코드를 보자.

01: [[NSNotificationCenter defaultCenter]
02: addObserver:self
03: selector:@selector(launchFinished:)
04: name:UIApplicationDidFinishLaunchingNotification
05: object:nil];

위 코드는 임의의 객체가 UIApplicationDidFinishLaunchingNotification 라는 통보를 발생시키면 self 객체의 launchFinished 를 호출하도록 한다. 코드의 2행과 3행의 인자는 통보가 발생했을 때 호출할 메서드를 지정한다. 여기서 이벤트는 문자열로 구분된다. 그래서 UIApplicationDidFinishLaunchingNotification 도 문자열로 정의되어 있다.

5행의 object 인자는 감시할 개체를 지정하기 위한 것이다. 만약 nil 을 지정하면 모든 객체를 대상으로 이벤트를 감시하게 된다. 만약 5행의 object 를 nil 로 설정하지 않고 특정 객체를 지정해 주면, 그 객체가 일치하는 문자열의 통보를 발생시킬 때만 통보를 받을 수 있다.

통보 이벤트를 더이상 감시할 필요가 없을때는 다음과 같이 제거해야 한다.

01: [[NSNotificationCenter defaultCenter] removeObserver:self];

removeObserver 메서드로 자신(self)이 더이상 통보를 받지 않겠다고 설정한다.

<그림1> 도움말 문서의 통보 항목

클래스의 도움말 문서를 보면 그 클래스가 발생시키는 통보를 확인 할 수 있다. 예를들어 그림1과 같이 UIWindow 클래스의 도움말을 보자. Notifications 라는 항목으로 자신이 발생시키는 통보에 대해서 설명하고 있다. UIWindowDidBecomeVisibleNotification 와 같은 통보 이름은 클래스의 헤더파일에 문자열로 정의되어 있다.

만약 직접 작성한 클래스에서 통보를 발생시키고 싶다면 어떻게 할까 ? 무척간단하다.

01: [[NSNotificationCenter defaultCenter]
02: postNotificationName:@"myEventOccured" object:self];

NSNotificationCenter 의 postNotificationName 메서드를 이용하면 된다. object 인자는 누가 이 통보 이벤트를 발생시키는 지를 설정한다.

<그림2> 예제

그림2의 예제를 직접 구현해 보자. ObjectA,ObjectB,ObjectC 는 각각 event1, myEventOccured,모든 통보 이벤트(nil) 에 관심이 있다.

01: [[NSNotificationCenter defaultCenter]
02: addObserver:ObjectA
03: selector:@selector(myEventHandler:)
04: name:@"event1"
05: object: nil];
06:

01: [[NSNotificationCenter defaultCenter]
02: addObserver:ObjectB
03: selector:@selector(myEventHandler:)
04: name:@"myEventOccured"
05: object: nil];
06:

01: [[NSNotificationCenter defaultCenter]
02: addObserver:ObjectC
03: selector:@selector(myEventHandler:)
04: name: nil
05: object: nil];
06:

ObjectC 는 name에 nil 을 설정했기 때문에 모든 이벤트를 통보받게 된다. 이제 객체X가 통보를 발생시킨다.

01: [[NSNotificationCenter defaultCenter]

02: postNotificationName:@"myEventOccured"

03: object:ObjectX

04: userInfo:[NSDictionary dictionaryWithObject:@”value1” forKey:@”data1”]

05: ];

위 코드가 실행되면 통보 센터는 ObjectX 에서 myEventOccured 통보가 발생했기 때문에, 이 통보를 감시하는 모든 객체의 메서드를 호출해 준다. 이때 감시 객체들은 ObjectX가 전달한 userInfo 딕셔너리 객체도 사용할 수 있다. 이벤트를 통보받는 메시지를 구현해 보자.

01: - (void) myEventHandler:(NSNotification *) notif
02: {
03: NSLog(@“%@ from %@”, [notif name], [notif object]);
04: NSDictionary *userInfo = [notif userInfo];
05: // userinfo 딕셔너리의 내용을 나열하자.
06: for (NSString *key in userInfo) {
07: NSLog(@“%@ = %@”, key, [userInfo objectForKey:key];
08: }
09: }

통보를 받으면 호출되는 이 메서드는 인자로 NSNotification 객체를 받는다. 이 객체는 통보에 대한 정보를 담고 있다. userInfo 속성은 통보를 보내는 객체가 추가 정보를 전달할 때 이용된다.

* 통보 큐

통보를 발생시킬때 호출하는 postNotificationName 메서드는 곧바로 모든 감시자의 메서드를 호출한다. 하지만 통보 큐를 이용하면 쓰레드가 유휴(Idle) 상태 일 때 메서드를 호출하게 만들 수 있다. 다음 코드를 보자.

01: [[NSNotificationCenter defaultCenter]
02: addObserver:objectA
03: selector:@selector(eventHandler:)
04: name:@"appLaunched" object:nil];
05:
06: [[NSNotificationQueue defaultQueue]
07: enqueueNotification:[NSNotification
08: notificationWithName:@"appLaunched"
09: object:self]
10: postingStyle:NSPostWhenIdle];

10행의 NSPostWhenIdle 옵션은 현재 쓰레드가 유휴상태일때 통보를 보내도록 한다.

Creative Commons License
Trackback 0 : Comments 3

Trackback Address :: http://maclove.pe.kr/trackback/27 관련글 쓰기

  1. 곰돌이 2010/02/16 16:56 Modify/Delete Reply

    설명감사해요

  2. biru99 2010/03/24 15:04 Modify/Delete Reply

    책을 보고 아무리 연구 해도 안나오길래 질문해 봅니다.
    A 버튼을 누르면 notification 등록을 하구요
    B 버튼을 누르면 쓰레드를 생성해서 norificationque 를 이용해서 데이터를 C 이벤트에 전송합니다 쓰레드는 무한 루프.
    C 이벤트에서 데이터를 받아서 UILabel 에 출력
    이 제가 원하는 일인데요

    현상황
    C 이벤트에서 notificationque를 전송 받긴 했는데
    UILabel 에 출력 되지가 않습니다.

    어떻게 해야 좋을지

    설명이 부족 하시면
    메일 주시면 메일로 간단한 제 소스를 전송 해 드리겠습니다.

  3. 샘플 2010/03/24 20:56 Modify/Delete Reply

    책에 있는 샘플로 provider를 컴파일 하고 OpenSSL 을 설치하였으며, 디렉토리까지 연결해 주었는데도 컴파일 에러가 나네요. 참고로 0.9.8m 임.

    error C2011: 'sockaddr' : 'struct' type redefinition

    아마도 컴파일 셋팅이 잘못된것 같기도 하지만, 아닌것 같기도 하고.. 잘안됨.

Write a comment

◀ PREV : [1] : ... [9] : [10] : [11] : [12] : [13] : [14] : [15] : [16] : [17] : ... [30] : NEXT ▶