Skip to content

Instantly share code, notes, and snippets.

@pietrobasso
Last active August 23, 2018 07:13
Show Gist options
  • Save pietrobasso/836cabbb04b352641c3bc368c023a724 to your computer and use it in GitHub Desktop.
Save pietrobasso/836cabbb04b352641c3bc368c023a724 to your computer and use it in GitHub Desktop.
Wrapper around the Notification User Info Keys used to get values from the user information dictionary of keyboard notifications. - UIKonf 2017 Conference https://www.youtube.com/watch?v=GzZO5VB1xUg
//
// NotificationCenter+AddObserver.swift
//
// Created by Pietro Basso on 27/02/2018.
//
import Foundation
import UIKit
/**
Wrapper around the Notification User Info Keys used to get values from the user information dictionary of keyboard notifications.
- Authors:
Chris Eidhof & Florian Kugler - [UIKonf 2017 Conference](https://www.youtube.com/watch?v=GzZO5VB1xUg)
*/
struct KeyboardPayload {
var beginFrame: CGRect
let endFrame: CGRect
let animationCurve: UIViewAnimationCurve
let animationDuration: TimeInterval
let isLocal: Bool
init(userInfo: [AnyHashable:Any]) {
beginFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as! CGRect
endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect
let animationCurveRaw = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UIViewAnimationCurve.RawValue
animationCurve = UIViewAnimationCurve(rawValue: animationCurveRaw)!
animationDuration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! TimeInterval
isLocal = userInfo[UIKeyboardIsLocalUserInfoKey] as! Bool
}
}
/**
Generic struct for binding a Notification Name to its Payload.
Convert a `userInfo` dictionary to `A` type.
`parse` takes one of these dictionaries and produces an `A`.
- Authors:
Chris Eidhof & Florian Kugler - [UIKonf 2017 Conference](https://www.youtube.com/watch?v=GzZO5VB1xUg)
*/
struct NotificationDescriptor<A> {
let name: Notification.Name
let parse: ([AnyHashable:Any]) -> A
}
extension NotificationCenter {
/**
Adds an entry to the notification center's dispatch table that includes a notification queue and a block to add to the queue, and an optional notification name and sender.
If a given notification triggers more than one observer block, the blocks may all be executed concurrently with respect to one another (but on their given queue or on the current thread).
The following example shows how you can register to receive locale change notifications.
- parameters:
- descriptor: The `NotificationDescriptor` for which to register the observer
- object: The object whose notifications the observer wants to receive; that is, only notifications sent by this sender are delivered to the observer.
- queue: The operation queue to which block should be added.
- block: The block to be executed when the notification is received.
- Authors:
Chris Eidhof & Florian Kugler - [UIKonf 2017 Conference](https://www.youtube.com/watch?v=GzZO5VB1xUg)
*/
@discardableResult func addObserver<A>(for descriptor: NotificationDescriptor<A>, object obj: Any?, queue: OperationQueue?, using block: @escaping (A) -> Void) -> NSObjectProtocol {
return addObserver(forName: descriptor.name, object: obj, queue: queue, using: { (note) in
block(descriptor.parse(note.userInfo!))
})
}
/**
Removes matching entries from the notification center's dispatch table.
If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method. Otherwise, you should call this method before observer or any object specified in `addObserver(for:object:queue:using:)` is deallocated.
- parameters:
- observer: Observer to remove from the dispatch table. Specify an observer to remove only entries for this observer.
- descriptor: `NotificationDescriptor` of the notification to remove from dispatch table. Specify a notification descriptor to remove only entries that specify this notification name.
- object: Sender to remove from the dispatch table. Specify a notification sender to remove only entries that specify this sender.
- Authors:
Chris Eidhof & Florian Kugler - [UIKonf 2017 Conference](https://www.youtube.com/watch?v=GzZO5VB1xUg)
*/
func removeObserver<A>(_ observer: Any, for descriptor: NotificationDescriptor<A>, object obj: Any?) {
return removeObserver(observer, name: descriptor.name, object: obj)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment