본문 바로가기
IT·디지털/IT 개발자 팁

[iOS] NSNotificationCenter 사용법 정리 (2025 최신 버전: NotificationCenter / Swift 포함)

by 가을이짱짱 2013. 12. 5.
반응형

iOS에서 NotificationCenter(구 NSNotificationCenter) 사용법 정리

간편로그인을 구현하다 보면 화면이나 객체 간 이벤트 전달을 위해 NotificationCenter를 자주 사용합니다. 예전에는 NSNotificationCenter를 많이 사용했지만, 지금은 Swift 기반으로 API가 단순해졌고 옵저버 제거 방식도 바뀌었습니다.

특히 과거에는 옵저버를 제거하지 않아 중복 호출, 다중 Noti 발생 등의 문제가 자주 발생했습니다. 이 글에서는 레거시 Objective-C 방식부터 2025년 최신 Swift 방식, 그리고 비동기 처리(NotificationQueue)까지 한 번에 정리해 드립니다.


1. (레거시) Objective-C에서 NSNotificationCenter 사용법

1-1. Notification 보내기 (post)

// 데이터 전달용 userInfo
NSDictionary *dic = @{@"firstKey": @"전송할 객체"};

[[NSNotificationCenter defaultCenter]
    postNotificationName:@"firstNotification"
                  object:self
                userInfo:dic];

1-2. Notification 받기 (addObserver)

[[NSNotificationCenter defaultCenter]
    addObserver:self
       selector:@selector(firstMethod:)
           name:@"firstNotification"
         object:nil];

- (void)firstMethod:(NSNotification *)notification {
    id value = notification.userInfo[@"firstKey"];
}

1-3. 반드시 옵저버 제거 필요 (중요!)

레거시 방식에서는 반드시 옵저버 제거가 필요했습니다.

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

옵저버를 제거하지 않으면 다중 호출 또는 메모리 해제 후 크래시 발생이 흔했습니다.


2. 2025년 기준 최신 Swift 방식

Swift에서는 NotificationCenter API가 개선되었으며, 특히 iOS 9+부터는 block-based observer 사용 시 removeObserver가 필요 없습니다.

2-1. Notification 보내기

NotificationCenter.default.post(
    name: .loginSuccess,
    object: nil,
    userInfo: ["userId": "1234"]
)

2-2. Notification 받기

let observer = NotificationCenter.default.addObserver(
    forName: .loginSuccess,
    object: nil,
    queue: .main
) { notification in
    if let userId = notification.userInfo?["userId"] as? String {
        print("로그인 성공: \(userId)")
    }
}

2-3. 블록 기반 옵저버는 제거가 자동 처리

addObserver(forName:object:queue:using:) 방식은 iOS가 내부적으로 자동 제거하므로 예전처럼 removeObserver를 호출하지 않아도 됩니다.

2-4. 그러나 필요하면 명시적으로 제거 가능

NotificationCenter.default.removeObserver(observer)

3. Notification의 동기 / 비동기 처리

3-1. 기본 방식(post)은 동기 처리

NotificationCenter.default.post()는 옵저버들의 콜백이 모두 끝나기 전까지 제어가 호출자에게 돌아가지 않는 동기(synchronous) 방식입니다.

3-2. 비동기 방식 필요 시

예전에는 다음처럼 performSelector + afterDelay(0) 방식으로 비동기 효과를 냈습니다.

[self performSelector:@selector(doComplexProcessing:)
           withObject:notification.object
           afterDelay:0.0f];

4. 고급 비동기 처리: NSNotificationQueue

NSNotificationQueue는 Notification을 비동기 큐에 넣는 방식이며, 동기/비동기를 선택할 수 있습니다.

NSNotification *noti =
    [NSNotification notificationWithName:@"testNotification" object:nil];

[[NSNotificationQueue defaultQueue]
    enqueueNotification:noti
          postingStyle:NSPostWhenIdle];

postingStyle 옵션

  • NSPostNow – 즉시(동기)
  • NSPostWhenIdle – run loop idle 시점(비동기)
  • NSPostASAP – 곧 ASAP 비동기 처리

5. 최신 기술: NotificationCenter + Combine

현재 시점에서 iOS에서는 Combine 기반 Notification 사용이 더욱 편리합니다.

import Combine

var cancellables = Set<AnyCancellable>()

NotificationCenter.default.publisher(for: .loginSuccess)
    .sink { notification in
        print("로그인 성공(Note): \(notification)")
    }
    .store(in: &cancellables)

이 방식은 옵저버 제거를 수동으로 할 필요 없이 cancellables의 생명주기에 따라 자동 관리됩니다.


정리

  • NSNotificationCenter는 현재도 사용 가능하지만 NotificationCenter로 업데이트됨
  • Objective-C 방식은 반드시 removeObserver 필요
  • Swift block-based observer는 자동 제거 (메모리 관리 개선)
  • 동기/비동기 처리 차이를 이해해야 다중 호출 문제를 방지할 수 있음
  • Combine을 사용하면 더 안전하고 편리하게 처리 가능

과거에는 옵저버 제거 누락으로 인해 크래시가 많이 발생했지만 지금은 훨씬 단순하고 안전하게 Notification을 사용할 수 있습니다.

반응형