协议扩展和addTarget崩溃并显示消息:由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:' - [Test.UIButton touchDown:]:无法识别的选择器发送到实例0x157eee8e0'
touchDown函数无法识别的问题在哪里?
protocol MyButtonProtocol {
var holdTimer: NSTimer? { get set }
}
extension MyButtonProtocol where Self: UIButton {
func enable() {
addTarget(self, action: "touchDown:", forControlEvents: UIControlEvents.TouchDown)
}
mutating func touchDown(sender: UIButton) {
print("Touch down!")
holdTimer = NSTimer(timeInterval: 1, target: self, selector: Selector("didTimeOut"), userInfo: nil, repeats: true)
}
}
// Usage:
let button = UIButton()
button.enable()
答案 0 :(得分:1)
这都很奇怪。
您的代码
let button = UIButton()
button.enable()
似乎不完整,因为实例button
未采用协议MyButtonProtocol
。
如果我写
class MyButton: UIButton, MyButtonProtocol {
var holdTimer: NSTimer?
func touch3(sender: AnyObject?) {
print("touch3 \(sender)")
}
}
然后
let myButton = MyButton()
myButton.enable() // this works ok
print("touch3: \(myButton.respondsToSelector(Selector("touch3:")))")
print("touchDown: \(myButton.respondsToSelector(Selector("touchDown:")))")
print("enable \(myButton.respondsToSelector(Selector("enable")))")
然后我看到输出
touch3: true
touchDown: false
enable false
所以程序成功调用了enable()
方法,但respondsToSelector
似乎没有检查协议扩展中的方法。 enable
正在运行,因为如果我将呼叫更改为
addTarget(self, action: "touch3:", forControlEvents: UIControlEvents.TouchDown)
然后成功到达touch3
。
这是NSObject.respondsToSelector
几周前我注意到我无法使用协议扩展中的函数覆盖super
中的函数。我认为这只是我误解的一种语言特征。也许这是同一问题的另一个症状?
答案 1 :(得分:0)
protocol MyButtonProtocol {
var holdTimer: NSTimer? { get set }
}
extension MyButtonProtocol where Self: UIButton {
var holdTimer: NSTimer? {
get {
return holdTimer
}
set {
holdTimer = newValue;
}
}
func enable() {
addTarget(self, action: "touchDown:", forControlEvents: UIControlEvents.TouchDown)
}
mutating func touchDown(sender: UIButton) {
print("Touch down!")
holdTimer = NSTimer(timeInterval: 1, target: self, selector: Selector("didTimeOut"), userInfo: nil, repeats: true)
}
}
extension UIButton: MyButtonProtocol {
}
// Usage:
let button = UIButton()
button.enable()
注意为UIButton编写的扩展,这是必需的,因为你编写了一个协议,但是UIButton需要实现它才能使它生效。我还在协议扩展中为holdTimer
编写了getter和setter。您也可以在UIButton
扩展名中写下此内容。
答案 2 :(得分:0)
来自Apple Bug报告小组的回答:
Engineering已确定此问题的行为符合预期 关于以下信息:Swift协议扩展不是 可用于Objective-C。只能使用类的扩展 目标C