logo

English

이곳의 프로그래밍관련 정보와 소스는 마음대로 활용하셔도 좋습니다. 다만 쓰시기 전에 통보 정도는 해주시는 것이 예의 일것 같습니다. 질문이나 오류 수정은 siseong@gmail.com 으로 주세요. 감사합니다.

[iOS, MacOS] NSNotification, NSNotificationCenter 사용법

by digipine posted Nov 02, 2017
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print

말이 약간 어렵지만 ' 내부에 시그널 패스가 연결되지 않은 곳에 메시지를 어떻게 던질 것인가라는 의문이 나온다면 NSNotificationCenter 를쓰는 것이 답이다  단순히 이야기 하자면 내에서 아무 데서나 메시지를 던지면  내의 아무데서나  메시지를 받을  있게  주는 것이 NSNotificationCenter  역활이다그리고  메시지 내용을 감싸는 껍데기가 NSNotification 오브젝트이다.

 

말이  어려운데 어떻게 해야  쉽게 표현이 가능   모르겠다어쨌거나 NSNotificationCenter 이용하는 방법의 기초에 관한 기록을 남긴다.

 

NSNotificationCenter

 

이름에서 보듯이 Notification Center 이다 NSNotification  중계해 주는 역활이다일반적으로 오브젝트를 생성해서 사용하지는 않고 대신 편하게 싱글턴 인스턴스를 받아 사용한다

 

// Objective-C Example: NSNotificationCenter Singleton Pattern

NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

 

// Swift Example: NSNotificationCenter Singleton Pattern

let notificationCenter = NSNotificationCenter.defaultCenter()

 

굳이 변수에 오브젝트 포인터를 저장   필요는 없다필요   바로 싱글턴 팩토리(defaultCenter) 불러서 쓰면 된다.

 

Observer 등록

 

Observer 라는 이름을 스타크래프트에서 많이 들어봤을 것이다투명하게 정찰하는 작고 귀여운......  생략하고옵저버란 중계되는NSNotification  원하는 것을 골라서 받을  있게  주는 기능을 한다.

 

우선 옵저버 몸뚱아리를 먼저 만들어 보자그냥 메서드 하나 만들고 인자로 NSNotification 오브젝트를 받도록 하면 된다.

 

// Objective-C Example: Notification Handler Method

- (void)didReceiveSimpleNotification:(NSNotification *)notification

{

    NSString *message = [notification.userInfo objectForKey:@"message"];

    NSLog(@"I've got the message %@", message);

}

 

// Swift Example: Notification Handler Method

func didReceiveSimpleNotification(notification: NSNotification) {

    let message: String? = notification.userInfo["message"] as? String

    println("I've got the message \(message)")

}

 

 코드는 NSNotification  통해 문자열(message) 전달받아 로그를 찍는 코드이다여기서 userInfo 라는 Dictionary(사전) 오브젝트를마음껏 이용   있다는 점을 알아두자

 

아래 코드는 "simple-notification" 이라는 이름의 Notification  받으면 위에서 만든 didReceiveSimpleNotification: 메서드를 호출하도록옵저버를 등록하는 예제이다

 

// Objective-C Example: Add Notification Observer with Selector

[[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(didReceiveSimpleNotification:)

                                             name:@"simple-notification"

                                           object:nil];

 

// Swift Example: Add Notification Observer with Selector

let nc = NSNotificationCenter.defaultCenter()

nc.addObserver(self, 

               selector: "didReceiveSimpleNotification:", 

               name: "simple-notification", 

               object: nil)

 

마지막의 object  제외하고는 용도가 분명해 보인다개인적으로 object  사용하지 않기에 nil 명시하고 있지만 필요하다면 레퍼런스 매뉴얼에서 용도를 파악해 보자.

 

여기까지면 옵저버 등록이 끝난다하지만 마지막으로 위의  가지 코드를  번에 블럭을 이용해 옵저버를 등록하는 방법도 있다.

 

// Objective-C Example: Add Notification Observer with Block

[[NSNotificationCenter defaultCenter] addObserverForName:@"simple-notification" 

                                                  object:nil 

                                                   queue:[NSOperationQueue mainQueue] 

                                              usingBlock:^(NSNotification *note) {

    NSString *message = [note.userInfo objectForKey:@"message"];

    NSLog(@"I've got the message %@", message);

}];

 

// Swift Example: Add Notification Observer with Closure

nc.addObserverForName("simple-notification", 

                      object: nil, 

                      queue: NSOperationQueue.mainQueue(), 

                      usingBlock: { (n: NSNotification!) -> () in

    let message: String? = n.userInfo["message"] as? String

    println("I've got the message \(message)")

})

 

위의 메서드를 분리해서 셀렉터를 등록하는 것에 비해 훨신 쓰기에는 편해 보인다하지만 queue 라는게 쓰이고 있는 점을 주의해야 한다위의예제에서는 mainQueue 불러다 썼기 때문에 UI 업데이트에 문제가 없겠지만 만약 다른 NSOperationQueue  만들어서 이걸 쓰고 싶다면 필요할  메인스레드를 사용하도록  처리해야 한다.

 

Post Notification

 

이제 옵저버를 만들고 옵저버가 Notification 메세지를 받을  있도록  놨으니 이제는 Notification    차례다아래 코드는 "simple-notification" 라는 이름의 Notification 쏘는 예제이다

 

// Objective-C Example: Post Notification

NSDictionary *userInfo = @{ @"message": @"Message using notification..." };

[[NSNotificationCenter defaultCenter] postNotificationName:@"simple-notification" 

                                                    object:nil 

                                                  userInfo:userInfo];

 

// Swift Example: Post Notification

let nc = NSNotificationCenter.defaultCenter()

let userInfo = [ "message": "Message using Notification" ]

nc.postNotificationName("simple-notification", object: nil, userInfo: userInfo)

"message" 라는 키에 원하는 데이터를 넣고 이를 이용해 NSDictionary 사전형 객체를 만들고 이를 userInfo 넣고 Notification  Post 한다간단히 말해 멋대로 만든 userInfo  메세지를 쏜다는 말이다. userInfo 원래 이런 용도로 쓰는 거니깐. :-)

 

이번에도 object  nil  안쓴다고 표기했는데 역시나 관심이 있다면 레퍼런스를 찾아서 활용도를 찾아보자.

 

Remove Observer

 

NSNotificationCenter  사용 방법이 간단해서 쉽게   있었는데 주의해야  점이 있다옵저버는 특정 클래스 오브젝트의 것이지만NSNotificationCenter  싱글턴 인스턴스라서 여러 오브젝트에서 공유한다그래서 옵저버를 등록한 오브젝트가 메모리에서 해제되면NSNotificationCenter 에서도 옵저버를 없앴다고 알려줘야 된다

 

// Objective-C Example: Remove Notification Observer from Deallocator

- (void)dealloc

{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

 

// Swift Example: Remove Notification Observer from deinit

deinit {

    NSNotificationCenter.defaultCenter().removeObserver(self)

}

 

 코드는 단순히 NSObject 형식의 모든 클래스에서 메모리가 해제될  호출되는 dealloc  옵저버를 제거하는 코드를 넣은 예제이다removeObserver:  이용해 자기 자신의 오브젝트에 속한 모든 옵저버를 NSNotificationCenter 에서 제거   있다

 

만약 제대로 제거해 주지 않으면 옵저버가 소속된 오브젝트가 해제 되었을  Notification  전달되면 100% 앱이 죽는다.

 

물론  외에도 필요   특정 옵저버만 제거   있는 removeObserver:name:object: 같은 메서드도 있으니 필요하면 찾아보자.

 

마무리

 

 Notification  활용도는 무궁무진하다예를 들어 서버와 통신하는 모듈을 별도로 만들고 UI 완전히 구분해 놓은 코드를 작성   통신모듈에서 UI 데이터를 어떻게 던져줄까 고민    가지 방법이   있다.

 

 외에 기존의 delegate 모델은 하나의 오브젝트 에서만 사용이 가능하니 여러 오브젝트에서 데이터를 전달 받아야 한다면 역시나 Notification 답이다.

TAG •

List of Articles
No. Subject Author Date Views
35 OSX 사파리 최신 버전 폰트 변경하기 file digipine 2017.11.03 1223
34 [Swift 3] TCPIP Socket 통신 클래스 소스 코드 및 사용법 digipine 2017.11.02 4645
33 [Swift 3] HTTP Request 사용하기, 클래스 소스코드 및 사용법 digipine 2017.11.02 9654
32 [macOS] Sandbox 정책 극복기 Accessing Security Scoped Resource 1 file digipine 2017.11.02 1774
31 [Objective C] NSString 앞뒤 공백 문자 및 줄바꿈 문자 제거 digipine 2017.11.02 1654
30 XCode 8 업데이트 후 Code Sign Error 발생 시 해결법 1 digipine 2017.11.02 710
» [iOS, MacOS] NSNotification, NSNotificationCenter 사용법 digipine 2017.11.02 1026
28 [iOS, MacOS] Singleton 싱글톤 패턴 사용하기 2 digipine 2017.11.02 1079
27 [iOS, MacOS] NSArray 정렬 Sorting에 대해서 digipine 2017.11.02 663
26 [iOS, MacOS] ATS 보안 정책 가이드 digipine 2017.11.02 566
25 OpenAL PDF, Sample Source file digipine 2017.11.02 796
24 Apple AppStore App Review 시 Reject 피하기 위한 방법 digipine 2017.11.02 446
23 iOS - UILabel 에서 AttributeString 사용하기 digipine 2017.11.02 639
22 iOS - BLE 장치용 ANCS Library for ANCS digipine 2017.11.02 947
21 iOS - UITextField의 Placeholder Color 색 변경하기 file digipine 2017.11.02 1152
20 iOS - sizeWithFont 메소드 deprecated와 sizeWithAttributes digipine 2017.11.02 607
19 iOS - Sleep Mode Blocking 방법, 앱실행시 슬립모드 진입 방지 digipine 2017.11.01 572
18 iOS , MacOS, iPhone용 GZipStream class 구현하기 digipine 2017.11.01 356
17 iOS - View 이동 전환 하기 총정리 digipine 2017.11.01 537
16 iOS - Openssl 빌드하기 digipine 2017.11.01 945
Board Pagination Prev 1 2 3 Next
/ 3