Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created November 24, 2016 12:56
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 chriseidhof/4bc50395ed583d79955f56922fde39bd to your computer and use it in GitHub Desktop.
Save chriseidhof/4bc50395ed583d79955f56922fde39bd to your computer and use it in GitHub Desktop.
import Cocoa
import PlaygroundSupport
let center = NotificationCenter.default
struct NotificationDescriptor<A> {
let name: Notification.Name
let convert: (Notification) -> A
}
struct PlaygroundPayload {
let page: PlaygroundPage
let needsIndefiniteExecution: Bool
}
let playgroundNotification = NotificationDescriptor<PlaygroundPayload>(name: Notification.Name("PlaygroundPageNeedsIndefiniteExecutionDidChangeNotification"), convert: { note in
let page = note.object as! PlaygroundPage
let needsIndefiniteExecution = note.userInfo!["PlaygroundPageNeedsIndefiniteExecution"] as! Bool
return PlaygroundPayload(page: page, needsIndefiniteExecution: needsIndefiniteExecution)
})
extension NotificationCenter {
func addObserver<A>(forDescriptor d: NotificationDescriptor<A>, using block: @escaping (A) -> ()) -> Token {
let t = addObserver(forName: d.name, object: nil, queue: nil, using: { note in
block(d.convert(note))
})
return Token(token: t, center: self)
}
}
class Token {
let token: NSObjectProtocol
let center: NotificationCenter
init(token: NSObjectProtocol, center: NotificationCenter) {
self.token = token
self.center = center
}
deinit {
center.removeObserver(token)
}
}
var token: Token? = center.addObserver(forDescriptor: playgroundNotification, using: { print($0) })
PlaygroundPage.current.needsIndefiniteExecution = true
token = nil
PlaygroundPage.current.needsIndefiniteExecution = false
// See also: https://talk.objc.io
//
// And: https://www.objc.io/blog/2015/01/19/functional-snippet-16-typed-notification-observers/ (for your own notifications)
@chriseidhof
Copy link
Author

An answer to the (very good) question about receiving notifications during deinit:

I managed to test this. Deinitialization / Deallocation happens in phases. First, the instance is set to nil (but not yet deinited/deallocated). Then, all the properties are set to nil. If a notification happens during that time, it will access the weak reference and see nil for self. Finally, the deinits are called (first for the object, then for its properties).

It's not that hard to test this yourself, and a very useful exercise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment