0

NSNotificationCenter을 통해 알림을 게시하는 클래스 Poster이 있습니다. 두 명의 다른 관찰자가 있습니다 : ObserverSuperclassObserverSubclass. ObserverSuperclassObserverSubclass의 수퍼 클래스입니다. 각 클래스가 알림에 다르게 응답하기를 바랍니다.블록 기반 NSNotificationCenter에서 하위 클래스를 관찰 하시겠습니까?

NSHipster에 따르면 최신 블록 기반 API 인 addObserverForName:object:queue:usingBlock:을 사용해야합니다.

ObserverSubclass의 초기화 방법에서 관찰자로 수퍼 클래스를 제거해야합니다. 블록 기반 API를 사용하기 때문에 반환 값인 addObserverForName:object:queue:usingBlock: - "관찰자 역할을하는 불투명 한 객체"를 참조해야합니다. ObserverSubclass.m

[[NSNotificationCenter defaultCenter] removeObserver:self.observer name:@"Help!" object:nil];

에서 ObserverSuperclass.m

self.observer = [NSNotificationCenter defaultCenter] addObserverForName:@"Help!" object:nil queue:nil usingBlock:^{old block}];

에서

@property (nonatomic, strong) id observer;

ObserverSuperclass.h에서 : 그래서 나는 다음과 같은 코드를 작성

self.observer = [NSNotificationCenter defaultCenter] addObserverForName:@"Help!" object:nil queue:nil usingBlock:^{new block}];

실제로 이것을 수행하는 가장 좋은 방법입니까? 여기에 블록 기반 API를 사용하는 것이 합리적이지는 않습니다.

+1

처리기 블록을 반환하는 메서드를 구현할 수 있습니다. 그런 다음 하위 클래스에서이 메서드를 간단하게 재정의하거나 선택기 기반 API를 사용하면됩니다. – Paulw11

+0

왜 수퍼 클래스를 관찰자로 제거해야합니까? 그 블록을 전혀 실행하지 않겠습니까? – Roberto

답변

2

이것은 내 의견으로는 전통적인 @selector 콜백 대신. 슈퍼 클래스는 관찰을 등록하고 기본 동작을 구현할 수 있습니다. 서브 클래스는 호출 된 뒤의 @selector를 오버라이드 (override) 할 필요가있다.

당신이 구현해야하는 방법은 다음과 같습니다 예를 들어

- (void)addObserver:(id)notificationObserver 
     selector:(SEL)notificationSelector 
      name:(NSString *)notificationName 
     object:(id)notificationSender 

, 슈퍼 클래스에 : 하위 클래스에서

- (instancetype) init 
{ ... 
    [[NSNotificationCenter defaultCenter] 
      addObserver:self 
       selector:@selector(oberserveThis:) 
        name:@"someEventName" 
       object:nil]; 
} 

- (void)observeThis:(NSNotification*)notification 
{ 
    // ... Do something here ... 
} 

:

- (void)observeThis:(NSNotification*)notification 
{ 
    // ... Do something else here ... 
} 

당신은 코드가 필요한 경우 관찰자가 특정 큐에서 실행되도록하려면 관찰 선택기 내에서 항상 디스패치를 ​​호출 할 수 있습니다. 나는 당신의 유스 케이스에서 블록 기반 접근법을 사용하는 것보다 훨씬 더 깨끗한 코드를 만든다고 생각한다.

+0

이것은 제가 온 결론입니다. 내가 서브 클래 싱하지 않는다는 것을 안다면 블록 기반 API 만 사용할 것입니다. – rizzes

0

코드가 정상적으로 보입니다.

논리를 매핑하면 하나의 관찰자 (수퍼 클래스 또는 하위 클래스) 만 필요하다는 논리가 적용됩니다. 하위 클래스의 관찰자가 수퍼 클래스의 관찰자를 제거하고 바꿉니다.

둘 다 동일한 알림 이름을 사용하도록하는 것도 유효합니다. 이 경우 새 인스턴스 변수 self.newObserver를 서브 클래스에 추가하고 해당 특성에 옵저버도 추가합니다. 그런 다음 두 블록 모두 "도움말!" 알림이 게시됩니다.

당신이하는 것은 당신이 성취하고자하는 것에 달려 있습니다.

더 이상 필요하지 않을 때 관찰자를 제거해야하거나 관찰자 블록 거래 대상 객체가 그 아래에서 할당 해제 될 때 충돌이 발생할 위험이 있습니다. (알림 센터에서 블록을 자동으로 유지하므로 선택기 기반 관찰자보다 블록 기반 관찰자가 적을 수 있으며 관찰자를 추가하는 객체가 할당 해제 된 경우에도 관찰자 블록이 계속 실행됩니다. 선택기 기반 관찰자 반드시 dealloc 메소드에서 옵저버를 제거해야한다는 것을 명심해야합니다. 관찰중인 통지 유형이 다시 게시되면 오브젝트가 할당 취소 된 후에 충돌해야합니다.)

+0

부모 - 자식 트리의 높이가 2보다 큰 경우이 시스템은 약간 어색 해집니다. (1과 2의 서브 클래스 인) 3 클래스는 self.observer, self.newObserver, self.newNewObserver를 가질 것입니다. 개별 속성으로 저장하는 대신 배열을 사용 하시겠습니까? – rizzes

+0

청취 클래스에 여러 명의 관찰자가있을 때 특히 더러워집니다. 여러 어레이 (또는 self.observer [N] 세트)를 사용해야합니까? – rizzes

+0

물론, 어레이는 괜찮을 것입니다. 기본 클래스가 초기화시에 생성하는 관찰자 객체의 변경 가능한 배열을 갖도록합니다. 자신의 옵저버를 필요로하는 각 서브 클래스는 새로운 옵저버를 작성해 그것을 배열에 추가합니다. 기본 클래스의 dealloc 메소드는 모든 클래스를 제거 할 수 있습니다. –