Swift函数的选择器字符串

时间:2015-01-26 19:12:45

标签: swift

给定一个函数引用,Swift中有没有办法将该函数的名称作为适合传递给NSSelectorFromString的字符串?

我希望将NSNotificationCenter addObserver包含一个带有函数引用而不是选择器字符串的版本:

addObserver(self, function: someCallback, name: "some notification", object: nil)

但是addObserver接受一个String选择器参数。

3 个答案:

答案 0 :(得分:4)

你正在重新发明一个不必要的轮子。 NSNotificationCenter 已经有一个观察方法,它接受一个函数(Objective-C调用"块"):

addObserverForName:object:queue:usingBlock:

所以就这样使用它。

答案 1 :(得分:0)

编辑:我将此留在这里是为了感兴趣,但这太复杂了(被问到如何问题,而不是目标)。除了现有的基于块的方法之外,还有this handy extension to it


我不会这样做。它太有限了,因为它会排除函数文字(匿名函数)。

相反,我会玩这个游戏:

  • 创建字典属性映射[String: Void -> ()](字符串到函数)
  • 当您注册新功能时,请编写一个唯一的随机密钥,并使用该密钥存储您在字典中传递的功能。
  • 注册选择器observer_dispatcher_<key>(或您喜欢的任何前缀)。
  • 实施resolveInstanceMethod:以动态创建您要求的任何observer_dispatcher_方法。他们都可以指向相同的IMP,例如:

(假设这是好Swift;我还没试过):

 void _observer_dispatcher(self: AnyObject, _cmd: Selector) {
    let name = // strip the leading stuff off of _cmd
    if let f = self.dispatchTable[name] {
         f()
     }
 }

(这仍然很草率;我必须更多地考虑正确的错误,但这是我进入的方向。)

答案 2 :(得分:0)

我仍然希望找到原始问题的答案,但根据@ matt的建议,我目前正在使用此扩展程序:

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)
    }

}

由于它隐式使用defaultCenter()并提供了objectqueue的默认值,我几乎总是将其传递为nil,因此可以进行更简洁的调用:

NSNotificationCenter.addObserver(doSomething, name: "some notification")

我喜欢它链接实际函数(doSomething),而不是字符串表示。它不是通用扩展,但我认为它覆盖了我注册通知的90%的情况。