Swiftのオブザーバーをデフォルトの通知センターに追加するにはどうすればよいですか?バッテリーレベルが変化したときに通知を送信するこのコード行を移植しようとしています。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
Swiftのオブザーバーをデフォルトの通知センターに追加するにはどうすればよいですか?バッテリーレベルが変化したときに通知を送信するこのコード行を移植しようとしています。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
回答:
Objective-C APIと同じですが、Swiftの構文を使用しています。
Swift 4.2およびSwift 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 Class Reference、Objective-C APIの操作を参照してください
UIDeviceBatteryLevelDidChangeNotification
引用符で囲まれていないのですか?文字列型です。
@objc
。
送信(投稿)通知:
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) {}
送信(投稿)通知:
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)
}
送信(投稿)通知
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
}
@objc
。
methodOFReceivedNotication
注釈を付けるかdynamic
、NSObjectのサブクラスのメンバーである必要があります。
object 0x7fd68852d710 of class 'TestNotifications.MyObject' does not implement methodSignatureForSelector: -- trouble ahead
、Unrecognized selector -[TestNotifications.MyObject methodOFReceivedNotication:]
これを行う良い方法は、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
式を含めます。
addObserver(_:selector:name:object:)
登録解除の方法とはかなり異なります。オブジェクトを返して保持してaddObserverForName(_:object:queue:usingBlock:)
渡す必要がありますremoveObserver:
addObserverForName(_:object:queue:usingBlock:)
。
UIViewController
で使用しself
、そのクロージャーで参照する場合は、使用する必要があり[weak self]
ます。そうしないと、参照サイクルとメモリリークが発生します。
Swift 3.0ではstruct
、NotificationCenterと同様に、多くの「文字列型」の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)
通知名を宣言する
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"]
}
通知を投稿する
NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
iOS 9およびOS X 10.11から。NSNotificationCenterオブザーバが割り当て解除されたときに自身を登録解除する必要はなくなりました。より詳しい情報
以下のためにblock
ベースの実装、あなたが使用したい場合は弱の強いダンスをする必要がself
ブロックの内側。より詳しい情報
ブロックベースのオブザーバーはより多くの情報を削除する必要があります
let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)
NSNotificationCenterを使用してデータを渡す
また、Swift 3.0ではNotificationCentreを使用し、Swift 2.0ではNSNotificationCenterを使用してデータを渡すこともできます。
Swift 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
}
}
Swift 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)
}
}
私は正常にセレクタを使用するには、次のいずれかの操作を行いすることができるよ- なし @objcで何かに注釈を付けるに:
NSNotificationCenter.defaultCenter().addObserver(self,
selector:"batteryLevelChanged:" as Selector,
name:"UIDeviceBatteryLevelDidChangeNotification",
object:nil)
または
let notificationSelector: Selector = "batteryLevelChanged:"
NSNotificationCenter.defaultCenter().addObserver(self,
selector: notificationSelector,
name:"UIDeviceBatteryLevelDidChangeNotification",
object:nil)
私のxcrunバージョンはSwift 1.2を示していますが、これはXcode 6.4およびXcode 7ベータ2(Swift 2.0を使用していると思っていました)で動作します。
$xcrun swift --version
Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
@objc
オブザーバークラスがから継承する場合は、注釈を付ける必要はありませんNSObject
。
String
をキャストする必要はありませんSelector
。:)
@objc
非NSObject
オブザーバークラスのメソッドからアノテーションを削除as Selector
し、String
セレクター名にキャストを追加し、通知が発生するとアプリがクラッシュしました。私のSwiftバージョンはあなたのものとまったく同じです。
@objc
注釈が機能し、この方法が機能しない限り、注釈を付け続けてください!
通知も削除する必要があります。
例
deinit
{
NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)
}
Swift 3では、Xcode 8.2:-バッテリー状態レベルの確認
//Add observer
NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil)
//Fired when battery level changes
func batteryStateDidChange(notification: NSNotification){
//perform manipulation here
}
NSNotificationCenterがiOS 11のSwift 4.0にオブザーバー構文を追加
NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
これは、keyboardWillShow通知名タイプ用です。利用可能なオプションから他のタイプを選択できます
セレクタは@objc func型で、キーボードの表示方法を処理します(これはユーザー関数です)
#selector
で注釈を付ける必要があることを意味します@objc
。例:@objc func keyboardShow() { ... }
Swift 4で1分間投げました!
Swift 5およびXcode 10.2:
NotificationCenter.default.addObserver(
self,
selector: #selector(batteryLevelDidChangeNotification),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
Swift 5通知オブザーバー
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelChanged), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}
@objc func batteryLevelChanged(notification : NSNotification){
//do here code
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}