Objective-C에서 NSNotificationCenter를 통해 메시지를주고 받습니까?


610

NSNotificationCenterObjective-C를 통해 메시지를 보내고 받으려고합니다 . 그러나이 작업을 수행하는 방법에 대한 예를 찾지 못했습니다. 메시지를 NSNotificationCenter어떻게 주고 받 습니까?


정말 매우 유용합니다. 감사합니다. 한 가지, addObserver 메소드에는 지정된 선택기 뒤에 세미 세미콜론이 없어야합니다 (적어도 내 버전에서는 예외가 발생했습니다). 위의 코드를 편집하려고 시도했지만 원래 코드의 형식 문제로 인해 변경 사항이 적용되지 않았습니다.
Braunius


2
이 질문은 너무 기본적이고 광범위합니다. 약간의
Google

이것은 관련 질문과 매우 유사합니다 : stackoverflow.com/questions/7896646/…
David Douglas

55
Stack Overflow 사용자가 그 유용성을 명확하게 언급했을 때 이것이 건설적이지 않은 것처럼 닫히는 것과 같은 질문은 터무니없는 것으로 나타났습니다
Chet

답변:


1019
@implementation TestClass

- (void) dealloc
{
    // If you don't remove yourself as an observer, the Notification Center
    // will continue to try and send notification objects to the deallocated
    // object.
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

- (id) init
{
    self = [super init];
    if (!self) return nil;

    // Add this instance of TestClass as an observer of the TestNotification.
    // We tell the notification center to inform us of "TestNotification"
    // notifications using the receiveTestNotification: selector. By
    // specifying object:nil, we tell the notification center that we are not
    // interested in who posted the notification. If you provided an actual
    // object rather than nil, the notification center will only notify you
    // when the notification was posted by that particular object.

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

    return self;
}

- (void) receiveTestNotification:(NSNotification *) notification
{
    // [notification name] should always be @"TestNotification"
    // unless you use this method for observation of other notifications
    // as well.

    if ([[notification name] isEqualToString:@"TestNotification"])
        NSLog (@"Successfully received the test notification!");
}

@end

... 다른 수업 어딘가에 ...

- (void) someMethod
{

    // All instances of TestClass will be notified
    [[NSNotificationCenter defaultCenter] 
        postNotificationName:@"TestNotification" 
        object:self];

}

2
[NSNotificationCenter defaultCenter]의 위치가 궁금합니다. AppDelegate에 배치하는 것이 가장 좋습니까?
fulvio

14
@Fulvio : 애플리케이션의 모든 부분에 영향을 줄 수있는 알림을 받거나 게시하는 경우이를 AppDelegate에 넣습니다. 단일 클래스에만 영향을주는 알림을 받거나 게시하는 경우 대신 해당 클래스에 넣으십시오.
dreamlax

1
@dreamlax Truth, 그러나이 질문은 대부분 알림 청취자를 필요 이상으로 오래 유지하는 새로운 iOS 개발자가 검색하기 때문에 주목할 가치가 있습니다. 이제 arc를 사용하면 보통 dealloc을 사용하지 않으므로 결과적으로 일부는 리스너를 해제 할 필요가 없다고 생각할 수 있습니다.
Vive

7
[super dealloc]dealloc-method 의 호출은 ARC 하에서 허용되지 않는다는 것도 언급 할 가치가 있습니다 . 나머지는 모두 좋습니다.
tommys

1
알림이 실행되고 관찰자가 없으면 어떻게됩니까? 알림이 유실 되었습니까? 아니면 새로운 관찰자 (나중에 생성)에게 선적 될 준비가되어있는 곳에 "저장"되어 있습니까?
superpuccio

226

dreamlax의 예 를 확장하려면 ... 알림과 함께 데이터를 보내려면

게시 코드에서 :

NSDictionary *userInfo = 
[NSDictionary dictionaryWithObject:myObject forKey:@"someKey"];
[[NSNotificationCenter defaultCenter] postNotificationName: 
                       @"TestNotification" object:nil userInfo:userInfo];

코드를 관찰 할 때 :

- (void) receiveTestNotification:(NSNotification *) notification {

    NSDictionary *userInfo = notification.userInfo;
    MyObject *myObject = [userInfo objectForKey:@"someKey"];
}

TestNotification은 NSString 유형이어야합니다. 인스턴스 변수 NSNotification입니까?
RomanHouse

1
selfreceiveTestNotification 메소드에서 옵저버 에 액세스 할 수 있습니까 ?

왜요? receiveTestNotification은 인스턴스 메소드이며 자체를 통해 인스턴스 자체에 액세스 할 수 있습니다.
Michael Peterson 22

그게 다야. 수신자 메소드에서 UserInfo를 얻는 방법을 찾고있었습니다.
hasan jan

모든 관찰자 아이디어가 모든 경우를 다루지는 않습니다. 앱이 작동하지 않았습니다. 알림 센터가 닫히고 알림 센터가 탭되었습니다. 옵저버 메소드가 호출되지 않습니다.
hasan

49

이것은 나를 도왔다 :

// Add an observer that will respond to loginComplete
[[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(showMainMenu:) 
                                                 name:@"loginComplete" object:nil];


// Post a notification to loginComplete
[[NSNotificationCenter defaultCenter] postNotificationName:@"loginComplete" object:nil];


// the function specified in the same class where we defined the addObserver
- (void)showMainMenu:(NSNotification *)note {
    NSLog(@"Received Notification - Someone seems to have logged in"); 
}

출처: http://www.smipple.net/snippet/Sounden/Simple%20NSNotificationCenter%20example


그것은 나를 위해 일했다! 감사합니다
Rakshitha Muranga Rodrigo

48

블록을 사용할 가능성도 있습니다 :

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] 
     addObserverForName:@"notificationName" 
     object:nil
     queue:mainQueue
     usingBlock:^(NSNotification *notification)
     {
          NSLog(@"Notification received!");
          NSDictionary *userInfo = notification.userInfo;

          // ...
     }];

애플의 문서


1
이것은 지금 상당히 구식 인 내 대답에 대한 좋은 업데이트입니다. 소개 또는 ARC 및 블록을 사용하면 알림 센터를 훨씬 쉽게 처리 할 수 ​​있습니다.
dreamlax

5
나도 그렇게 생각했지만 사실 이기에는 너무 좋은 것으로 판명되었습니다. 이 경우 addObserver가 반환하고 나중에 제거하는 옵저버를 유지해야하므로 새 메서드를 만드는 것만 큼 복잡하지 않습니다. 더 많은 정보 : toastmo.com/blog/2012/12/04/…
Andrew

42

NSNotificationCenter를 사용하여 뷰를 업데이트하는 경우 다음을 호출하여 메인 스레드에서 뷰를 보내는 것을 잊지 마십시오 dispatch_async.

dispatch_async(dispatch_get_main_queue(),^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"my_notification" object:nil];
});

1
메인 스레드에서 발생 해야하는 알림 포스트입니까, 아니면 실제로 뷰를 업데이트 할 때, 즉 메인 스레드로 디스패치하는 알림을 수신하는 메소드 내부입니까?
Crashalot

1
알림을 보내는 스레드는 기능을 실행하고 UI를 변경하려는 스레드입니다. 다음과 같이 함수 내부의 기본 스레드에 디스패치를 ​​사용할 수도 있습니다. D : 같은 결과를해야한다, 그것의 더 나은 perheps
eiran

1
@eiran, 정말 고마워요, dispatch_async 안에 쓴 후에 만 ​​작동했습니다
Arshad Shaik

2

초보자를위한 선별 된 답변의 SWIFT 5.1

class TestClass {
    deinit {
        // If you don't remove yourself as an observer, the Notification Center
        // will continue to try and send notification objects to the deallocated
        // object.
        NotificationCenter.default.removeObserver(self)
    }

    init() {
        super.init()

        // Add this instance of TestClass as an observer of the TestNotification.
        // We tell the notification center to inform us of "TestNotification"
        // notifications using the receiveTestNotification: selector. By
        // specifying object:nil, we tell the notification center that we are not
        // interested in who posted the notification. If you provided an actual
        // object rather than nil, the notification center will only notify you
        // when the notification was posted by that particular object.

        NotificationCenter.default.addObserver(self, selector: #selector(receiveTest(_:)), name: NSNotification.Name("TestNotification"), object: nil)
    }

    @objc func receiveTest(_ notification: Notification?) {
        // [notification name] should always be @"TestNotification"
        // unless you use this method for observation of other notifications
        // as well.

        if notification?.name.isEqual(toString: "TestNotification") != nil {
            print("Successfully received the test notification!")
        }
    }
}

... 다른 수업 어딘가에 ...

 func someMethod(){
        // All instances of TestClass will be notified
        NotificationCenter.default.post(name: "TestNotification", object: self)
 }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.