Reputation: 17762
Given a function reference, is there a way in Swift to get the name of that function as a string suitable for passing to NSSelectorFromString
?
I'd like to wrap NSNotificationCenter
's addObserver
with a version that takes a function reference instead of a selector string:
addObserver(self, function: someCallback, name: "some notification", object: nil)
But addObserver
takes a String selector argument.
Upvotes: 3
Views: 1216
Reputation: 299275
Edit: I'm leaving this here for interest, but it's way too complicated (got wrapped up in how the question was asked, rather than the goal). Beyond the existing block-based approach, there's also this handy extension to it.
I wouldn't do it this way. It's too limiting because it would exclude function literals (anonymous functions).
Instead, I would play this game:
[String: Void -> ()]
(string to function)observer_dispatcher_<key>
(or whatever prefix you like).resolveInstanceMethod:
to dynamically create any observer_dispatcher_
method you're requested. They can all point to the same IMP
, something like:(assuming this is good Swift; I haven't tried it):
void _observer_dispatcher(self: AnyObject, _cmd: Selector) {
let name = // strip the leading stuff off of _cmd
if let f = self.dispatchTable[name] {
f()
}
}
(This is still pretty sloppy; I'll have to think about the correct correct impl more, but this is the direction I'd go in.)
Upvotes: 0
Reputation: 17762
I'd still like to find an answer to my original question, but based on @matt's suggestion, I'm currently using this extension:
extension NSNotificationCenter {
class func addObserver(function: (NSNotification!) -> (), name: String? = nil, object: AnyObject? = nil, queue: NSOperationQueue? = nil) {
defaultCenter().addObserverForName(name, object: object, queue: nil, usingBlock: function)
}
}
Since it implicitly uses defaultCenter()
and provides defaults for object
and queue
, which I'd almost always pass nil for, it allows for a more succinct call:
NSNotificationCenter.addObserver(doSomething, name: "some notification")
I like that it links against the actual function (doSomething
), rather than a string representation. It's not a general purpose extension, but I think it covers 90% of the cases where I register for notifications.
Upvotes: 0
Reputation: 534950
You're reinventing an unnecessary wheel. NSNotificationCenter already has an observation method that takes a function (what Objective-C calls a "block"):
addObserverForName:object:queue:usingBlock:
So just use that.
Upvotes: 4