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.