[상단] iOS 감청 모드 시리즈의 NSNotificationCenter 사용

5420 단어 대상Class
NSNotificationCenter
이것에 대해 더 말할 필요가 없다. 바로 뉴스 통지 메커니즘이다. 방송과 유사하다.관찰자는 정보센터에 관심 있는 것만 등록하면 되고, 이 메시지를 보낼 곳이 있을 때 알림센터는 이 메시지를 등록한 대상에게 발송한다.이렇게 하면 여러 대상 사이의 결합을 해소하는 작용을 한다.애플은 우리에게 이 NSNotification Center를 봉하여 통지의 등록과 제거를 편리하게 할 수 있도록 했다.그러나 어떤 사람들의 자세는 여전히 약간의 문제가 있다. 다음은 정확한 자세를 보자!
바른 자세의remove
NSNotificationCenter에 등록하기만 하면 반드시 Remove의 존재가 있어야 한다는 것은 모두의 공통된 인식이다.그러나 여러분이 사용하실 때 UIView Controller에서addObserver를 제거하지 않았고 끊지도 않은 것 같습니다!많은 사람들이 저와 같은 의문을 가지고 있을 거예요. ARC를 사용했기 때문인가요?대상이 소각될 때 자동으로 nil로 설정되었나요?아니면 사과는 이런 걸 실현할 때 어떤 신기한 방식을 썼을까요?다음은 우리가 한 걸음 한 걸음 탐구해 보자.
우선 NSNotificationCenter에 있는ddObserver에 이 대상을 인용 계수에 1을 추가하지 않았기 때문에 주소만 저장합니다.이 조작을 검증하기 위해서 우리는 코드의 테스트를 해 봅시다.
알림 등록을 위한 테스트 클래스:
@implementation MRCObject

- (id)init
{
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test" object:nil];
    }
    return self;
}

- (void)test
{
    NSLog(@"=================");
}

- (void)dealloc
{
    [super dealloc];
}

@end
이 종류는 매우 간단하다. 바로 초기화할 때 그에게 통지를 등록하는 것이다.하지만 삭제할 때remove 작업을 하지 않습니다.VC에서 이 객체를 만든 다음 제거하고 마지막으로 이 알림을 보냅니다.
- (void)viewDidLoad {
    [super viewDidLoad];

    MRCObject *obj = [[MRCObject alloc] init];
    [obj release];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
}
이vc에 들어간 후에 우리는 끊는 것을 발견하였다.인쇄된 정보는 다음과 같습니다.
2015-01-19 22:49:06.655  [1158:286268] *** -[MRCObject test]: message sent to deallocated instance 0x17000e5b0
우리는 야생 지침 대상에게 메시지를 보냈기 때문에 끊었다는 것을 알 수 있다.이런 점에서 애플의 실현도 거의 다르지 않다. 대상의 주소만 저장했고 폐기할 때nil로 설정하지 않았다.
이 점은 addObserver 이후에remove 작업이 있어야 한다는 것을 증명할 수 있다.
이제 UIViewController에 알림을 등록하고 제거하지 않고 끊을지 확인합니다.
- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test" object:nil];
}
우선navigationController로 이 페이지에 들어가서 팝을 내보냅니다.마지막으로 알림을 보내는 단추를 누르면 이벤트:
- (void)didButtonClicked:(id)sender
{
   [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
}
네가 어떻게 이 버튼을 눌러도 그는 끊지 않는다.이제 답답하지 않아요?코드 안에remove 작업이 없는지 찾아볼 수 있지만 NSNotification Center 쪽에서 제거했습니다. 그렇지 않으면 위쪽 지침에 문제가 생길 것입니다.보아하니 UIView Controller가 스스로 소각할 때 우리를 도와 몰래 제거했다는 것만 설명할 수 있을 것 같다.
그럼 우리는 어떻게 증명합니까?우리는 원본 코드를 볼 수 없기 때문에 호출되었는지 모르겠다.이때 우리는 이 통지 센터에서 착수할 수 있다!!!어떻게 손을 대지?나는 UIView Controller가 소각할 때remove 방법을 사용했다는 것을 증명하기만 하면 우리의 추측이 옳다는 것을 증명할 수 있다.이럴 때는 우리의 강력한 유형이라는 특성이 필요하다.NSNotificationCenter에 범주를 추가하여 그의 - (void) removeObserver: (id) observer 메서드를 다시 작성합니다.
- (void)removeObserver:(id)observer
{
   NSLog(@"====%@ remove===", [observer class]);
}
이렇게 우리 VC에서 이 종류를 가져오고 팝이 나와서 무슨 일이 일어났는지 보세요!
2015-01-19 22:59:00.580  [1181:288728] ====TestViewController remove===
어때요?시스템의 UIViewController가 삭제할 때 이 방법을 사용했다는 것을 증명할 수 있습니까?(개발할 때 기존의 방법을 카테고리로 덮어쓰는 것을 권장하지 않습니다. 카테고리 방법은 더욱 높은 우선권을 가지기 때문에 다른 곳에 영향을 미칠 수 있습니다. 여기는 시험용으로만 사용합니다.)
이상에서도 당신이 소각하지 않을 때 [[NSNotificationCenter default Center]removeObserver:self]를 직접 호출하지 말라고 일깨워 주었습니다.이 방법은 시스템 등록 알림을 제거할 수 있기 때문이다.
올바른 자세 주의
우리가 개발하는 동안 우리는 자주 이런 코드를 볼 수 있다.
- (void)viewWillAppear:(BOOL)animated
{
   [super viewWillAppear:animated];
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"test" object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
   [super viewWillDisappear:animated];
   [[NSNotificationCenter defaultCenter] removeObserver:self name:@"test" object:nil];
}
페이지가 나타날 때 알림을 등록하고 페이지가 사라질 때 알림을 제거합니다.이쪽은 주의해야 한다. 반드시 쌍으로 나타나야 한다. 만약view Will Appear에서add Observer가view Will Disappear에서remove Observer가 없다면, 소식이 발생했을 때, 당신의 방법은 여러 번 호출될 것이다. 이 점을 명심해야 한다.
정확한 자세의 다중 스레드 알림
먼저 애플의 공식 설명을 살펴보자.
Regular notification centers deliver notifications on the thread in which the notification was posted. Distributed notification centers deliver notifications on the main thread. At times, you may require notifications to be delivered on a particular thread that is determined by you instead of the notification center. For example, if an object running in a background thread is listening for notifications from the user interface, such as a window closing, you would like to receive the notifications in the background thread instead of the main thread. In these cases, you must capture the notifications as they are delivered on the default thread and redirect them to the appropriate thread.
의미는 간단합니다. NSNotificationCenter 메시지의 수용 루트는 메시지를 보내는 루트에 기반을 두고 있습니다.즉 동기화됩니다. 따라서 때때로, 당신이 보낸 메시지는 메인 라인에 없을 수도 있고, UI를 조작하려면 반드시 메인 라인에 있어야 하며, 그렇지 않으면 응답하지 않는 상황이 발생할 수도 있습니다.따라서 메시지 알림을 받을 때 실행할 라인을 선택하는 것에 주의하세요.다음은 예시 코드를 보겠다
// 
- (void)test
{
   if ([[NSThread currentThread] isMainThread]) {
       NSLog(@"main");
   } else {
       NSLog(@"not main");
   }
   dispatch_async(dispatch_get_main_queue(), ^{
       //do your UI
   });

}

// 
- (void)sendNotification
{
   dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
   dispatch_async(defaultQueue, ^{
       [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:nil];
   });
}

좋은 웹페이지 즐겨찾기