我有这样的代码:
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:
,句点。
因此,将此用例报告给快速演进的长期解决方案。 短期内,使用某种解决方法。
顺便说一句,您可能会发现阅读(甚至参与(此线程很有趣。