[ios] Swift에서 NSNotification에 대한 관찰자를 제거하는 곳은 어디입니까?

및 사용할 수 없기 NSNotification때문에 Swift 에서 관찰자를 어디에서 제거해야 합니까?viewDidUnloaddealloc()



답변

와 동일한 기능을하는 아래 방법을 사용하십시오 dealloc.

deinit {
    // Release all resources
    // perform the deinitialization
}

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

Swift Deinitializer


답변

현재 아이폰 OS 9 (및 OS X 10.11), 당신은 관찰자를 제거 할 필요가 없습니다 당신은 블록 기반의 관찰자하지만 사용하지 않을 경우, 자신을. 시스템은 관찰자를 위해 제로화 약한 참조를 사용하기 때문에 가능합니다.

그리고 블록 기반 관찰자를 사용 하는 경우 클로저의 캡처 목록에서 자신을 약하게[weak self] 캡처 하고 메서드 에서 관찰자제거하십시오deinit . self에 대한 약한 참조를 사용하지 않으면 deinit알림 센터가 무기한으로 강력한 참조를 보유하므로 메소드 (따라서 해당 관찰자 제거)가 호출되지 않습니다.

자세한 내용 은 OS X v10.11 및 iOS 9 용 Foundation Release Notes 에서 확인할 수 있습니다 .

관찰자가 영점 약한 참조로 저장 될 수있는 경우 기본 저장소는 관찰자를 영점 약한 참조로 저장합니다. 또는 객체를 약하게 저장할 수없는 경우 (즉, 런타임을 방지하는 사용자 지정 유지 / 해제 메커니즘이 있습니다.) 개체를 약하게 저장할 수 없음) 개체를 약하지 않은 제로화 참조로 저장합니다. 이것은 옵저버가 할당 해제 방법에서 등록을 취소 할 필요가 없음을 의미합니다.

-[NSNotificationCenter addObserverForName : object : queue : usingBlock] 메서드를 통한 블록 기반 관찰자는 시스템이 여전히 이러한 관찰자에 대한 강력한 참조를 보유하고 있기 때문에 더 이상 사용하지 않을 때 등록 해제해야합니다.


답변

세 가지 방법을 사용할 수 있습니다.

  1. popViewController, 뒤 navigationController또는 dismissViewControllerAnimated:

    deinit {
        print("Remove NotificationCenter Deinit")
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  2. viewDidDisappear, 이미 다음 뷰 컨트롤러가 된 후 제거하십시오.

    override func viewDidDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  3. viewWillDisappear -다음보기를 열기 전 :

    override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    

Swift 3.0 구문 :

NotificationCenter.default.removeObserver(self)


답변

Swift 4.2에서 이것은 관찰자를 제거 할 수있는 방법 중 하나입니다.

deinit {
    NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}

viewDidLoad 클래스에서 addObserver 알림 설정

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}


답변

Swift는 파괴되기 전에 클래스의 인스턴스에서 호출되는 deinit 메소드를 제공합니다.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html


답변

또한이 방법을 사용해야한다는 점을 지적하고 싶습니다.

func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)

대신에

func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol

후자는 관찰자를 제거하지 않을 것입니다 (최근에이 문제에 빠졌습니다). iOS9을 사용하는 경우 전자는 관찰자를 제거합니다.


답변

deinit {
    NotificationCenter.default.removeObserver(self)
}