Last active
July 10, 2017 04:57
-
-
Save jsorge/a216f95d871371d1684f45519a59c5a6 to your computer and use it in GitHub Desktop.
How to make Notifications type safe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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