[ios] Swift의 NSNotificationCenter addObserver

Swift에서 옵저버를 기본 알림 센터에 어떻게 추가합니까? 배터리 잔량이 변경되면 알림을 보내는이 코드 줄을 이식하려고합니다.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];



답변

Objective-C API와 동일하지만 Swift의 구문을 사용합니다.

스위프트 4.2 및 스위프트 5 :

NotificationCenter.default.addObserver(
    self,
    selector: #selector(self.batteryLevelChanged),
    name: UIDevice.batteryLevelDidChangeNotification,
    object: nil)

관찰자가 Objective-C 오브젝트에서 상속하지 않는 경우 메소드를 @objc선택 자로 사용하려면 메소드 접 두부 를 사용해야합니다.

@objc private func batteryLevelChanged(notification: NSNotification){
    //do stuff using the userInfo property of the notification object
}

참조 NSNotificationCenter 클래스 참조를 , 오브젝티브 C API와 상호 작용


답변

스위프트 4.0 및 Xcode 9.0+ :

발송 (포스트) 알림 :

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

또는

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])

알림 받기 :

NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

수신 된 알림에 대한 함수 메소드 핸들러 :

@objc func methodOfReceivedNotification(notification: Notification) {}

스위프트 3.0 및 Xcode 8.0 이상 :

발송 (포스트) 알림 :

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

알림 받기 :

NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

수신 된 알림에 대한 메소드 핸들러 :

func methodOfReceivedNotification(notification: Notification) {
  // Take Action on Notification
}

알림 제거 :

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

스위프트 2.3 및 Xcode 7 :

발송 (포스트) 알림

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

알림 받기 (받기)

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)

수신 된 알림에 대한 메소드 핸들러

func methodOfReceivedNotification(notification: NSNotification){
  // Take Action on Notification
}


역사적인 Xcode 버전의 경우 …



발송 (포스트) 알림

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

알림 받기 (받기)

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil)

알림 제거

NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed

수신 된 알림에 대한 메소드 핸들러

func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

@objc로 클래스 또는 대상 메소드에 주석을 답니다.

@objc private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

// Or

dynamic private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}


답변

이 작업을 수행하는 좋은 방법은 Objective-C 코드에서 자주 사용되는 방법이 addObserver(forName:object:queue:using:)아닌 방법 을 사용하는 것 addObserver(_:selector:name:object:)입니다. 첫 번째 변형의 장점은 @objc메소드 에서 속성 을 사용할 필요가 없다는 것입니다 .

    func batteryLevelChanged(notification: Notification) {
        // do something useful with this information
    }

    let observer = NotificationCenter.default.addObserver(
        forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
        object: nil, queue: nil,
        using: batteryLevelChanged)

원하는 경우 메소드 대신 클로저를 사용할 수도 있습니다.

    let observer = NotificationCenter.default.addObserver(
        forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
        object: nil, queue: nil) { _ in print("?") }

반환 된 값을 사용하여 나중에 알림 수신을 중지 할 수 있습니다.

    NotificationCenter.default.removeObserver(observer)

이 방법을 사용할 때 또 다른 이점이 있었는데, 이는 컴파일러가 정적으로 확인할 수없는 선택기 문자열을 사용할 필요가 없으므로 메소드의 이름이 바뀌면 깨지기 쉽지 않습니다. 그러나 Swift 2.2 및 나중에 해당 문제를 해결하는 #selector표현식 이 포함됩니다 .


답변

Xcode 8의 스위프트 3.0

Swift 3.0은 structNotificationCenter와 마찬가지로 많은 “문자열 유형”API를 “래퍼 유형”으로 대체했습니다 . 알림은 이제가 struct Notfication.Name아닌로 식별 됩니다 String. Swift 3로 마이그레이션 안내서를 참조하십시오. .

이전 사용법 :

// Define identifier
let notificationIdentifier: String = "NotificationIdentifier"

// Register to receive notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name: notificationIdentifier, object: nil)

// Post a notification
NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil)

새로운 Swift 3.0 사용법 :

// Define identifier
let notificationName = Notification.Name("NotificationIdentifier")

// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)

// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)

모든 시스템 알림 유형은 이제 정적 상수로 정의됩니다 Notification.Name. 즉 .UIDeviceBatteryLevelDidChange, .UIApplicationDidFinishLaunching,.UITextFieldTextDidChange , 등

Notification.Name시스템 알림과 일관성을 유지하기 위해 고유 한 사용자 지정 알림으로 확장 할 수 있습니다 .

// Definition:
extension Notification.Name {
    static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}

// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)


답변

  1. 알림 이름 선언

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
  2. 두 가지 방법으로 관찰자를 추가 할 수 있습니다.

    사용 Selector

    NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: .purchaseDidFinish, object: nil)
    
    @objc func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }

    또는 사용 block

    NotificationCenter.default.addObserver(forName: .purchaseDidFinish, object: nil, queue: nil) { [weak self] (notification) in
        guard let strongSelf = self else {
            return
        }
    
        strongSelf.myFunction(notification: notification)
    }
    
    func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
  3. 알림 게시

    NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])

iOS 9 및 OS X 10.11에서. 더 이상 NSNotificationCenter 옵저버가 할당 해제 될 때 자체 등록을 해제 할 필요가 없습니다.더 많은 정보

A의 block기반 구현을 사용하려는 경우 약한 강한 춤을 할 필요가self 블록 내에서. 더 많은 정보

블록 기반 관찰자는 더 많은 정보를 제거해야합니다.

let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)


답변

NSNotificationCenter를 사용하여 데이터 전달

swift 3.0에서는 NotificationCentre를 사용하고 swift 2.0에서는 NSNotificationCenter를 사용하여 데이터를 전달할 수도 있습니다.

스위프트 2.0 버전

[NSObject : AnyObject] 유형의 선택적인 사전 인 userInfo를 사용하여 정보를 전달 하시겠습니까?

let imageDataDict:[String: UIImage] = ["image": image]

// Post a notification
 NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil, userInfo: imageDataDict)

// Register to receive notification in your class
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: notificationName, object: nil)

// handle notification
func showSpinningWheel(notification: NSNotification) {
  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image
  }
}

스위프트 3.0 버전

userInfo는 이제 [AnyHashable : Any]? Swift에서 사전 리터럴로 제공하는 인수로

let imageDataDict:[String: UIImage] = ["image": image]

// post a notification
 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict)
// `default` is now a property, not a method call

// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)

// handle notification
func showSpinningWheel(_ notification: NSNotification) {

  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image
  }
}

NotificationCentre (swift 3.0) 및 NSNotificationCenter (swift 2.0)를 사용한 소스 패스 데이터


답변

에서 스위프트 (5)

ViewControllerB에서 ViewControllerA로 데이터를 수신하려면

ViewControllerA (수신기)

import UIKit

class ViewControllerA: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()

        //MARK: - - - - - Code for Passing Data through Notification Observer - - - - -
        // add observer in controller(s) where you want to receive data
        NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
    }

    //MARK: - - - - - Method for receiving Data through Post Notificaiton - - - - -
    @objc func methodOfReceivedNotification(notification: Notification) {
        print("Value of notification : ", notification.object ?? "")
    }
}

ViewControllerB (발신자)

import UIKit

class ViewControllerB: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //MARK: - - - - - Set data for Passing Data Post Notification - - - - -
        let objToBeSent = "Test Message from Notification"
        NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
    }

}