Skip to content

Instantly share code, notes, and snippets.

@jsorge
Last active July 10, 2017 04:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsorge/a216f95d871371d1684f45519a59c5a6 to your computer and use it in GitHub Desktop.
Save jsorge/a216f95d871371d1684f45519a59c5a6 to your computer and use it in GitHub Desktop.
How to make Notifications type safe
import UIKit
struct CustomNotification: NotificationDescriptor {
struct Output {
let name: String
let type: String
}
typealias Payload = Output
let noteName = Notification.Name("CustomNotificationPosted")
}
class Foo {
var token: NotificationToken?
init() {
token = NotificationCenter.default.addObserver(descriptor: CustomNotification(), using: { (output) in
print("received a \(output.name) of type \(output.type)")
})
}
}
do {
var myFoo: Foo? = Foo()
let output = CustomNotification.Output(name: "thing", type: "superclass")
let note = CustomNotification().encode(payload: output)
NotificationCenter.default.post(note)
myFoo = nil
}
import Foundation
protocol CustomNotificationDescriptor {
associatedtype Payload
var noteName: Notification.Name { get }
func encode(payload: Payload) -> Notification
func decode(_ note: Notification) -> Payload
}
extension CustomNotificationDescriptor {
var _modelKey: String {
return "ModelKey"
}
func encode(payload: Payload) -> Notification {
let info = [_modelKey: payload]
let note = Notification(name: noteName, object: nil, userInfo: info)
return note
}
func decode(_ note: Notification) -> Payload {
let model = note.userInfo![_modelKey] as! Payload
return model
}
}
class NotificationToken {
let token: NSObjectProtocol
let center: NotificationCenter
init(token: NSObjectProtocol, center: NotificationCenter) {
self.token = token
self.center = center
}
deinit {
center.removeObserver(token)
}
}
extension NotificationCenter {
func addObserver<A: CustomNotificationDescriptor>(descriptor: A, queue: OperationQueue? = nil, using block: @escaping (A.Payload) -> ()) -> NotificationToken {
let token = addObserver(forName: descriptor.noteName, object: nil, queue: queue, using: { note in
block(descriptor.decode(note))
})
return NotificationToken(token: token, center: self)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment