在我的ViewController类中,我有一个函数:
func updateTimes() {
// (code)
}
我创建了一个计时器:
class ViewController: NSViewController {
var timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector:
#selector(ViewController.updateTimes),
userInfo: nil,
repeats: true)
编译器对此很满意。 在运行时,当计时器触发时,我得到一个异常:
发送到实例0x6000000428b0的无法识别的选择器
我做错了什么吗?
正如我对NaGib ToroNgo的回答的评论所写的那样,他给了我们一个很好的建议。
选择器可能不会发送到ViewController
的实例。
我想ViewController
会采取这种形式:
class ViewController: UIViewController {
var timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(ViewController.updateTimes),
userInfo: nil,
repeats: true)
//...(Other property declarations or method definitions)...
func updateTimes() {
// (code)
}
}
变量timer
声明为实例属性,self
用于初始值timer
。(在一些旧版本的 Swift 中,这种用法会导致错误,所以我认为这一行存在于任何方法中。
在当前版本的 Swift 中(使用 Swift 3.1/Xcode 8.3.3 测试(,上面的代码不会导致错误,但self
被解释为NSObjectProtocol
中声明self()
方法的方法引用。因此,Selector("updateTimes")
被发送到表示方法引用(curried 函数(的闭包,而不是发送到ViewController
的实例。
闭包没有名为updateTimes
的方法,这导致了异常:
发送到实例的无法识别的选择器
将初始值代码移动到某个实例上下文中,然后self
表示ViewController
的实例:
class ViewController: UIViewController {
var timer: Timer? //<- Keep `timer` as an instance property, but move the initial value code into `viewDidLoad()`.
//...(Other property declarations or method definitions)...
override func viewDidLoad() {
super.viewDidLoad()
//Do initialize the timer in the instance context.
timer = Timer.scheduledTimer(timeInterval: 5,
target: self,
selector: #selector(self.updateTimes),
userInfo: nil,
repeats: true)
//...
}
//In Swift 3, `@objc` is not needed, just for a preparation for Swift 4
@objc func updateTimes() {
// (code)
}
}
我相信这不会造成unrecognized selector
例外。
您提供的代码似乎很完美。我认为问题是,不知何故,您的视图控制器被释放或有悬空的指针。
是时候告别选择器了!!使用以下代码
Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { (timer) in
// check self for nil before using
}