Skip to content

Instantly share code, notes, and snippets.

@beccadax
Last active November 29, 2017 09:56
Show Gist options
  • Save beccadax/64845dc0b3fec0a27d87 to your computer and use it in GitHub Desktop.
Save beccadax/64845dc0b3fec0a27d87 to your computer and use it in GitHub Desktop.
A safer block-based NSNotification observer API. This method automatically uses an unowned reference to the observing object, and automatically unregisters the observer when it's deallocated. This implementation is kind of a toy, but a useful toy.
// Note: You could just as easily write this in Objective-C, but I didn't want to. So nyeh.
//
// Typical usage:
// NSNotificationCenter.defaultCenter().addObserver(self, name: SomeNotification, object: someObject) { self_, note in
// ...do something with self_...
// }
//
// It would benefit from being allowed to shadow `self` in a block parameter list, but Swift
// forbids that. (http://www.openradar.me/18550356)
import Foundation
public extension NSNotificationCenter {
func addObserver<T: AnyObject>(observer: T, name aName: String?, object anObject: AnyObject?, queue: NSOperationQueue? = NSOperationQueue.mainQueue(), handler: (observer: T, notification: NSNotification) -> Void) -> AnyObject {
let observation = addObserverForName(aName, object: anObject, queue: queue) { [unowned observer] note in
handler(observer: observer, notification: note)
}
ObservationRemover(observation).makeRetainedBy(observer)
return observation
}
}
private class ObservationRemover: NSObject {
let observation: NSObjectProtocol
init(_ obs: NSObjectProtocol) {
observation = obs
super.init()
}
func makeRetainedBy(owner: AnyObject) {
observationRemoversForObject(owner).addObject(self)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(observation)
}
}
private var ObservationRemoverKey: UnsafePointer<Void> = nil
private func observationRemoversForObject(object: AnyObject) -> NSMutableArray {
if ObservationRemoverKey == nil {
withUnsafePointer(&ObservationRemoverKey) { pointer in
ObservationRemoverKey = UnsafePointer<Void>(pointer)
}
}
var retainedRemovers = objc_getAssociatedObject(object, ObservationRemoverKey) as NSMutableArray?
if retainedRemovers == nil {
retainedRemovers = NSMutableArray()
objc_setAssociatedObject(object, ObservationRemoverKey, retainedRemovers, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))
}
return retainedRemovers!
}
@azizdev
Copy link

azizdev commented Aug 27, 2016

Hi, tried to implement this code and i got two errors:
Line 51:
var retainedRemovers = objc_getAssociatedObject(object, ObservationRemoverKey) as NSMutableArray?
and line 54:
objc_setAssociatedObject(object, ObservationRemoverKey, retainedRemovers, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))

I fixed them by changing line 51 to:
var retainedRemovers = objc_getAssociatedObject(object, ObservationRemoverKey) as? NSMutableArray
and line 54 to be:
objc_setAssociatedObject(object, ObservationRemoverKey, retainedRemovers, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)

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