Swift 运行时异常:无法识别的选择器



在我的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
}

最新更新