[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
#1 楼
它与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类参考,与Objective进行交互-C API
评论
谢谢!我不知道如何在Swift中传递选择器名称。
–浆果蓝
2014年6月4日23:30
@BerryBlue,以上解决方案对您有用吗?我相信,如果您的函数接受NSNotification作为参数,则需要将“ batteryLevelChanged”更改为“ batteryLevelChanged:”。
–奥尔尚斯克
2014年6月5日在2:46
@Olshansk是的,您是对的。您确实需要。谢谢!
–浆果蓝
2014年6月6日15:51
为什么UIDeviceBatteryLevelDidChangeNotification不在引号中?这是一个字符串类型。
– kmiklas
14年6月18日在21:16
确保使用@objc注释类或目标方法。
–克拉斯
2014年8月24日23:32
#2 楼
Swift 4.0和Xcode 9.0+:发送(发布)通知:
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
OR
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])
接收(Get)通知:
NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
接收通知的函数方法处理程序:
@objc func methodOfReceivedNotification(notification: Notification) {}
Swift 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)
}
Swift 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
}
评论
确保使用@objc注释类或目标方法。
–克拉斯
2014年8月24日23:24
@goofansu您确定吗?我认为您必须在纯Swift类中添加它。
–克拉斯
2014年12月30日上午10:25
methodOFReceivedNotication必须使用动态注释或为NSObject子类的成员。
–克拉斯
2014-12-30 13:37
如果没有,我得到类'TestNotifications.MyObject'的运行时警告对象0x7fd68852d710不实现methodSignatureForSelector:-麻烦,无法识别的选择器-[TestNotifications.MyObject methodOFReceivedNotication:]
–克拉斯
2014-12-30 13:38
@TaylorAllred,非常感谢您查看我的回答。非常感谢您的建议。我已经改变了。请检查一下。
– Renish Dadhaniya
2015年2月26日在4:12
#3 楼
一个很好的方法是使用addObserver(forName:object:queue:using:)
方法,而不是Objective-C代码中经常使用的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:
–卢卡斯·古森(Lucas Goossen)
16-2-26在13:57
这需要进行更新以包括对addObserverForName(_:object:queue:usingBlock :)返回的对象的注销。
–双曲线
16-3-29在16:55
这是一个比connor或Renish的答案更好的答案(在本文发表时均为以上),因为它可以避免使用Obj-C #selector方法。结果是,IMO更加迅速且正确。谢谢!
–patr1ck
16年7月16日在17:41
记住,如果在UIViewController中使用此函数并在该闭包中引用self,则需要使用[weak self],否则将有一个参考周期和内存泄漏。
–罗布N
17-10-11在13:39
#4 楼
Xcode 8中的Swift 3.0Swift 3.0已将
struct
“包装器类型”替换为许多“字符串类型” API,例如NotificationCenter。现在通过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)
#5 楼
声明通知名称
extension Notification.Name {
static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
}
您可以通过两种方式添加观察者:
使用
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)
评论
“从iOS 9和OS X 10.11开始。在释放时,NSNotificationCenter观察者不再需要注销自身。”这仅适用于基于选择器的观察者。基于块的观察者仍然需要删除。
– Abhinav
18-11-20在4:04
如果块中只有一行代码,则无需进行弱强共舞。您可以只使用像self?.myFunction这样的弱项。好吧,ObjC就是这种情况,我认为在Swift中也是如此。
– Malhal
7月3日8:04
#6 楼
使用NSNotificationCenter传递数据还可以在swift 3.0中使用NotificationCentre传递数据,在swift 2.0中使用NSNotificationCenter传递数据。
Swift 2.0版本
使用userInfo是[NSObject:AnyObject]类型的可选字典吗?
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)传递源传递数据
评论
很高兴听到它对您有所帮助:)
– Sahil
17年12月13日在17:11
#7 楼
在Swift 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)
}
}
#8 楼
我能够执行以下一项操作以成功使用选择器-无需使用@objc进行注释:NSNotificationCenter.defaultCenter().addObserver(self,
selector:"batteryLevelChanged:" as Selector,
name:"UIDeviceBatteryLevelDidChangeNotification",
object:nil)
OR
let notificationSelector: Selector = "batteryLevelChanged:"
NSNotificationCenter.defaultCenter().addObserver(self,
selector: notificationSelector,
name:"UIDeviceBatteryLevelDidChangeNotification",
object:nil)
我的xcrun版本显示了Swift 1.2,并且可以在Xcode 6.4和Xcode 7 beta 2(我认为应该使用Swift 2.0)上运行:
$xcrun swift --version
Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
评论
如果观察者类继承自NSObject,则无需使用@objc进行注释。
– Antonio Favata
2015年7月9日在13:33
而且您也不需要显式地将String强制转换为Selector。 :)
– Antonio Favata
2015年7月9日在13:33
@alfvata:我的观察者类不继承自NSObject。它继承自Swift风格的AnyObject。将字符串显式转换为Selector可以避免执行其他与Objective-C相关的其他解决方法。
–Leanne
2015年7月9日在22:00
我不确定我是否了解它的工作原理。我从非NSObject观察器类的方法中删除了@objc批注,在字符串选择器名称中添加了as Selector强制转换,并且当通知触发应用程序崩溃时。我的Swift版本与您的完全相同。
– Antonio Favata
15年7月10日在9:50
@alfavata,我不知道该怎么说。我现在在使用Xcode Beta 4,并且仍在工作。我的项目完全是Swift。没有Objective-C组件。也许会有所作为。也许项目设置中有些不同。有许多可能性!我会说:只要@objc注释对您有用,而这种方法不起作用,请继续注释!
–Leanne
15年7月27日在15:47
#9 楼
在Swift 2.2-XCode 7.3中,我们将#selector
用于NSNotificationCenter
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
#10 楼
我们也应该删除通知。例如。
deinit
{
NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue: "notify"), object: nil)
}
评论
我相信自iOS 9以来您就不需要此功能。它是自动完成的。
– Viktor Kucera
17年9月25日在7:16
#11 楼
Swift 5 Notification Observeroverride 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)
}
#12 楼
在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
}
#13 楼
NSNotificationCenter在iOS 4.0的Swift 4.0中添加了观察者语法 NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
这是适用于keyboardWillShow通知名称类型的。可以从可用选项中选择其他类型
选择器为@objc func类型,用于处理键盘的显示方式(这是您的用户功能)
评论
只是为了向阅读此答案的任何人澄清:“选择器的类型为@objc函数...”意味着与#selector关联的函数必须使用@objc进行注释。例如:@objc func keyboardShow(){...}这使我在Swift 4中呆了一分钟!
–Leanne
17-10-17在22:29
#14 楼
Swift 5和Xcode 10.2:NotificationCenter.default.addObserver(
self,
selector: #selector(batteryLevelDidChangeNotification),
name: UIDevice.batteryLevelDidChangeNotification,
object: nil)
评论
您具体问什么?选择器如何工作?我没有意识到“选择器”类型只是Swift中的一个字符串。在文档中没有提及它。
stackoverflow.com/questions/36910965 / ...