你如何在Swift 3中创build自定义通知?

在Objective-C中,自定义通知只是一个普通的NSString,但在Swift 3的WWDC版本中它并不明显。

你也可以使用这个协议

protocol NotificationName { var name: Notification.Name { get } } extension RawRepresentable where RawValue == String, Self: NotificationName { var name: Notification.Name { get { return Notification.Name(self.rawValue) } } } 

然后将您的通知名称定义为任何您想要的enum 。 例如:

 class MyClass { enum Notifications: String, NotificationName { case myNotification } } 

并使用它

 NotificationCenter.default.post(name: Notifications.myNotification.name, object: nil) 

这样通知名称将从Foundation Notification.Name分离出来。 如果Notification.Name的实现更改,则只需修改协议即可。

有一种更清洁(我认为)的方式来实现它

 extension Notification.Name { static let onSelectedSkin = Notification.Name("on-sekected-skin") } 

然后你可以像这样使用它

 NotificationCenter.default.post(name: .onSelectedSkin, object: selectedSkin) 

Notification.post被定义为:

 public func post(name aName: NSNotification.Name, object anObject: AnyObject?) 

在Objective-C中,通知名称是一个普通的NSString。 在Swift中,它被定义为NSNotification.Name。

NSNotification.Name被定义为:

 public struct Name : RawRepresentable, Equatable, Hashable, Comparable { public init(_ rawValue: String) public init(rawValue: String) } 

这是奇怪的,因为我希望它是一个枚举,而不是一些看似没有更多好处的自定义结构。

在NSNotification的通知中有一个typealias.Name:

 public typealias Name = NSNotification.Name 

令人困惑的是Swift中存在Notification和NSNotification

因此,为了定义自己的自定义通知,请执行以下操作:

 public class MyClass { static let myNotification = Notification.Name("myNotification") } 

然后调用它:

 NotificationCenter.default().post(name: MyClass.myNotification, object: self) 

更简单的方法:

 let name:NSNotification.Name = NSNotification.Name("notificationName") NotificationCenter.default.post(name: name, object: nil) 

您可以将自定义初始值设定项添加到NSNotification.Name

 extension NSNotification.Name { enum Type: String { case foo, bar } init(_ type: Type) { self = NSNotification.Name(type.rawValue) } } 

用法:

 NotificationCenter.default.post(name: Notification.Name(.foo), object: nil) 
 NSNotification.Name(rawValue: "myNotificationName") 

这只是参考

 // Add observer: NotificationCenter.default.addObserver(self, selector: #selector(notificationCallback), name: MyClass.myNotification, object: nil) // Post notification: let userInfo = ["foo": 1, "bar": "baz"] as [String: Any] NotificationCenter.default.post(name: MyClass.myNotification, object: nil, userInfo: userInfo) 

我做了我自己的实现,从那里和那里混合的东西,并认为这是最方便的。 分享谁可能感兴趣的人:

 public extension Notification { public class MyApp { public static let Something = Notification.Name("Notification.MyApp.Something") } } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(self.onSomethingChange(notification:)), name: Notification.MyApp.Something, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } @IBAction func btnTapped(_ sender: UIButton) { NotificationCenter.default.post(name: Notification.MyApp.Something, object: self, userInfo: [Notification.MyApp.Something:"foo"]) } func onSomethingChange(notification:NSNotification) { print("notification received") let userInfo = notification.userInfo! let key = Notification.MyApp.Something let something = userInfo[key]! as! String //Yes, this works :) print(something) } } 

使用枚举的优点是我们让编译器检查名称是否正确。 减less潜在的问题,并使重构更容易。

对于那些喜欢使用枚举而不是引用string来通知名称的人来说,这段代码可以做到这一点:

 enum MyNotification: String { case somethingHappened case somethingElseHappened case anotherNotification case oneMore } extension NotificationCenter { func add(observer: Any, selector: Selector, notification: CheckoutNotification, object: Any? = nil) { addObserver(observer, selector: selector, name: Notification.Name(notification.rawValue), object: object) } func post(notification: MyNotification, object: Any? = nil, userInfo: [AnyHashable: Any]? = nil) { post(name: NSNotification.Name(rawValue: notification.rawValue), object: object, userInfo: userInfo) } } 

那么你可以像这样使用它:

 NotificationCenter.default.post(.somethingHappened) 

虽然与这个问题无关,但是可以使用storyboard segues来完成,以避免键入带引号的string:

 enum StoryboardSegue: String { case toHere case toThere case unwindToX } extension UIViewController { func perform(segue: StoryboardSegue) { performSegue(withIdentifier: segue.rawValue, sender: self) } } 

然后,在你的视图控制器上,像这样调用它:

 perform(segue: .unwindToX) 
Interesting Posts