Reputation: 439
I have code like this:
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
)
}
}
Unfortunately it crashes when I start timer the program crashes with
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[xyz.A doFoo:]: unrecognized selector sent to instance 0x7fb2041c4ac0'
How i can make it work (I want to keep implementation of doFoo inside protocol)?
If I move doFoo into A class definition everything works fine, but as i said i want to implement this function inside protocol.
In other words I need selector that says
"Hey I point to function named "doFoo" that is implemented as extension to FooP"
Right now selector seems to say
"Hey I point to function named "doFoo" that is implemented in A class"
Upvotes: 1
Views: 950
Reputation: 10136
The problem is, NSTimer
and the whole Selector()
business are Objective-C stuff and do work in Swift domain thanks to bridging. However, Swift's default protocol implementations are not bridged to Objective-C wonderland (yet), and that's why your timer fails. Basically, from Objective-C perspective objects of type A
do not respond to a selector doFoo:
, period.
So, report this use-case to swift-evolution for the long-term solution. Short-term, use some sort of a workaround.
BTW, you might find it interesting to read (or even participate) in this thread.
Upvotes: 1
Reputation: 17534
Try to play in your playground. Your trouble is, that there is no possibility to define @objc func in protocol extension. So, see possible workaround
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()
Why it works for you if you move doFoo inside class A? That is because your class inherits from NSObject, so @objc keyword is not necessary.
Upvotes: 1