快速选择器到协议功能



我有这样的代码:

protocol FooP {
   ...
}
extension FooP {
   func doFoo() {
      print("foo")
   }
   func doFoo(timer: NSTimer) {
      doFoo()
   }
}
class A : NSObject, UITableViewDataSource, FooP {
   var timer : NSTimer?
   ...
   func startUpdating() {
      timer = NSTimer.scheduledTimerWithTimeInterval(
         1.0,
         target: self,
         selector: Selector("doFoo:"),
         userInfo: nil, 
         repeats: true
      )
   }
}

不幸的是,当我启动程序崩溃的计时器时,它崩溃了

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[xyz.A doFoo:]: unrecognized selector sent to instance 0x7fb2041c4ac0'

我怎样才能让它工作(我想在协议中保持doFoo的实现(?

如果我将doFoo移动到A类定义中,一切正常,但正如我所说,我想在协议中实现这个函数。

换句话说,我需要选择器说

"Hey I point to function named "doFoo" that is implemented as extension to FooP"

现在选择器似乎说

"Hey I point to function named "doFoo" that is implemented in A class"

试着在你的操场上玩。您的问题是,不可能在协议扩展中定义@objc func。因此,请参阅可能的解决方法

import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
import Foundation
protocol FooP {
}
extension FooP {
    func doFoo() {
        print("foo")
    }
    func doFoo(timer: NSTimer) {
        print("dofoo")
        doFoo()
    }
}
class A: FooP {
    var timer : NSTimer?
    @objc func foo(timer: NSTimer) {
        doFoo(timer)
    }
    func startUpdating() {
        timer = NSTimer.scheduledTimerWithTimeInterval(
            1.0,
            target: self,
            selector: "foo:",
            userInfo: nil,
            repeats: true
        )
    }
}
let a = A()
a.startUpdating()

如果你在A类内移动doFoo,为什么它对你有用?这是因为您的类继承自 NSObject,因此不需要@objc关键字。

问题是,NSTimer和整个Selector()业务都是 Objective-C 的东西,并且由于桥接而在 Swift 域中工作。 然而,Swift 的默认协议实现还没有桥接到 Objective-C 仙境,这就是你的计时器失败的原因。 基本上,从Objective-C的角度来看,类型A的对象响应选择器doFoo:,句点。

因此,将此用例报告给快速演进的长期解决方案。 短期内,使用某种解决方法。

顺便说一句,您可能会发现阅读(甚至参与(此线程很有趣。

最新更新