Last active
November 29, 2017 09:56
-
-
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.
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
// 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! | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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)