uiapplicationdidbecomeactivenotification notification example defaultcenter swift nsnotificationcenter nsnotifications nsnotification swift3

defaultcenter - swift nsnotificationcenter example



¿Cómo se crean notificaciones personalizadas en Swift 3? (12)

En Objective-C, una notificación personalizada es solo un NSString simple, pero no es obvio en la versión WWDC de Swift 3 exactamente lo que debería ser.


Esto es solo referencia

// 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)


Hay una forma más limpia (creo) de lograrlo

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

Y luego puedes usarlo así

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


Hice mi propia implementación mezclando cosas de un lado a otro, y considero que esto es lo más conveniente. Compartir para quien pueda estar interesado:

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) } }


La respuesta de @ CesarVarela es buena, pero para que el código sea un poco más limpio, puede hacer lo siguiente:

extension Notification.Name { typealias Name = Notification.Name static let onSelectedSkin = Name("on-selected-skin") static let onFoo = Name("on-foo") }


La ventaja de usar enumeraciones es que obtenemos el compilador para verificar que el nombre sea correcto. Reduce posibles problemas y facilita la refactorización.

Para aquellos a quienes les gusta usar enumeraciones en lugar de cadenas citadas para nombres de notificaciones, este código hace el truco:

enum MyNotification: String { case somethingHappened case somethingElseHappened case anotherNotification case oneMore } extension NotificationCenter { func add(observer: Any, selector: Selector, notification: MyNotification, 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) } }

Entonces puedes usarlo así:

NotificationCenter.default.post(.somethingHappened)

Aunque no está relacionado con la pregunta, lo mismo se puede hacer con segues del guión gráfico, para evitar escribir cadenas citadas:

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

Luego, en su controlador de vista, llámelo como:

perform(segue: .unwindToX)


Manera más fácil:

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


Notification.post se define como:

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

En Objective-C, el nombre de la notificación es un NSString simple. En Swift, se define como NSNotification.Name.

NSNotification.Name se define como:

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

Esto es un poco extraño, ya que esperaría que fuera una Enum, y no una estructura personalizada con aparentemente no más beneficio.

Hay un typealias en Notification for NSNotification.Name:

public typealias Name = NSNotification.Name

La parte confusa es que tanto la Notificación como la NSNotification existen en Swift

Entonces, para definir su propia notificación personalizada, haga algo como:

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

Entonces para llamarlo:

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


Puede agregar un inicializador personalizado a NSNotification.Name

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

Uso:

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


Puedo sugerir otra opción que es similar a lo que sugirió @CesarVarela.

extension Notification.Name { static var notificationName: Notification.Name { return .init("notificationName") } }

Esto te permitirá publicar y suscribirte en notificaciones fácilmente.

NotificationCenter.default.post(Notification(name: .notificationName))

Espero que esto te ayudará.


También podría usar un protocolo para esto

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

Y luego defina sus nombres de notificación como una enum cualquier lugar que desee. Por ejemplo:

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

Y úsalo como

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

De esta forma, los nombres de las notificaciones se desacoplarán de Foundation Notification.Name . Y solo tendrá que modificar su protocolo en caso de que cambie la implementación de Notification.Name .


si usa notificaciones personalizadas solo de cadena, no hay razón para extender ninguna clase excepto String

extension String { var notificationName : Notification.Name{ return Notification.Name.init(self) } }


NSNotification.Name(rawValue: "myNotificationName")