[objective-c] Objective-C : NSNotification에 대한 관찰자를 제거 할 위치는 어디입니까?

객관적인 C 클래스가 있습니다. 그 안에 init 메소드를 만들고 NSNotification을 설정했습니다.

//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(getData)
                                             name:@"Answer Submitted"
                                           object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self]이 수업 에서는 어디에 설정 합니까? 나는 a UIViewController에 대해 그것을 viewDidUnload메소드에 추가 할 수 있다는 것을 알고 있습니다. 그래서 방금 목표 c 클래스를 생성했다면 무엇을해야할까요?



답변

일반적인 대답은 “더 이상 알림이 필요하지 않은 즉시”입니다. 이것은 분명히 만족스러운 대답이 아닙니다.

관찰자 등록을 완전히 취소 할 수있는 마지막 기회이므로 관찰자로 사용하려는 클래스의 [notificationCenter removeObserver: self]메서드 dealloc에 호출을 추가하는 것이 좋습니다 . 그러나 이것은 알림 센터가 죽은 개체를 알리기 때문에 충돌로부터 만 보호합니다. 개체가 아직 알림을 적절하게 처리 할 수있는 상태가 아니거나 더 이상없는 경우 알림 수신으로부터 코드를 보호 할 수 없습니다. 이를 위해 … 위를 참조하십시오.

편집 (답이 내가 생각했던 것보다 더 많은 주석을 끌어내는 것 같기 때문에) 여기서 제가 말하려는 것은 알림 센터에서 관찰자를 제거하는 것이 가장 좋은시기에 대한 일반적인 조언을 제공하기가 정말 어렵습니다.

  • 사용 사례 (어떤 알림이 관찰됩니까? 언제 전송됩니까?)
  • 관찰자의 구현 (알림을받을 준비가 된 시점은 언제입니까? 더 이상 준비되지 않은 시점은 언제입니까?)
  • 관찰자의 의도 된 수명 (보기 또는보기 컨트롤러와 같은 다른 개체에 연결되어 있습니까?)

그래서 제가 생각해 낼 수있는 가장 일반적인 조언은 앱을 보호하는 것입니다. 적어도 한 번의 실패 가능성에 대비하여에서 removeObserver:춤을 추십시오. dealloc그것이 (객체의 삶에서) 마지막 지점이기 때문에 깨끗하게 할 수 있습니다. 이것이 의미하지 않는 것은 ” dealloc이 호출 될 때까지 제거를 연기하면 모든 것이 잘 될 것입니다”입니다. 대신 개체가 더 이상 알림을받을 준비가되지 않거나 필요하지 않으면 즉시 관찰자 제거합니다 . 바로 그 순간입니다. 안타깝게도 위에서 언급 한 질문에 대한 답을 알지 못해서 그 순간이 언제인지 짐작조차 할 수 없습니다.

항상 안전하게 removeObserver:객체를 여러 번 사용할 수 있습니다 (주어진 관찰자와의 첫 번째 호출을 제외하고 모두 nops가됩니다). 그러니 : dealloc확실하게하기 위해 (다시) 생각해보세요 .하지만 무엇보다도 먼저 : 적절한 순간에하세요 (사용 사례에 따라 결정됨).


답변

참고 : 이것은 100 % 테스트 및 작동되었습니다.

빠른

override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)

    if self.navigationController!.viewControllers.contains(self) == false  //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.

        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

PresentedViewController

override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)

    if self.isBeingDismissed()  //presented view controller
    {
        // remove observer here
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

목표 -C

에서 iOS 6.0 > version의 더 나은 것은에서 관찰자를 제거하기 위해 viewWillDisappear같은 viewDidUnload방법이 사용되지 않습니다.

 [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];

많은 배 더있다 remove observer뷰가 제거 된 경우 navigation stack or hierarchy.

- (void)viewWillDisappear:(BOOL)animated{
 if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.

        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}

PresentedViewController

- (void)viewWillDisappear:(BOOL)animated{
    if ([self isBeingDismissed] == YES) ///presented view controller
    {
        // remove observer here
        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}


답변

iOS 9부터 더 이상 관찰자를 제거 할 필요가 없습니다.

OS X 10.11 및 iOS 9.0에서 NSNotificationCenter 및 NSDistributedNotificationCenter는 더 이상 할당이 취소 될 수있는 등록 된 관찰자에게 알림을 보내지 않습니다.

https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter


답변

관찰자가 뷰 컨트롤러 에 추가 된 경우에는 추가 viewWillAppear하고 제거 하는 것이 좋습니다 viewWillDisappear.


답변

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


답변

일반적으로 나는 그것을 dealloc방법에 넣었다 .


답변

dealloc을 사용할 수 없기 때문에 신속하게 deinit를 사용하십시오.

deinit {
    ...
}

Swift 문서 :

deinitializer는 클래스 인스턴스가 할당 해제되기 직전에 호출됩니다. init 키워드를 사용하여 intializer를 작성하는 방법과 유사하게 deinit 키워드를 사용하여 deinitializer를 작성합니다. Deinitializer는 클래스 유형에서만 사용할 수 있습니다.

일반적으로 인스턴스 할당이 취소 될 때 수동 정리를 수행 할 필요가 없습니다. 그러나 자체 리소스로 작업하는 경우 몇 가지 추가 정리를 직접 수행해야 할 수 있습니다. 예를 들어 사용자 정의 클래스를 만들어 파일을 열고 일부 데이터를 쓰는 경우 클래스 인스턴스가 할당 해제되기 전에 파일을 닫아야 할 수 있습니다.