Swift 运行时异常:无法识别的选择器
Swift Runtime exception: unrecognized selector
在我的ViewControllerclass中,我有一个函数:
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版本中(用Swift3.1/Xcode8.3.3测试),上面的代码不会报错,但是self
是解释为在 NSObjectProtocol
中声明的 self()
方法的方法引用。因此,Selector("updateTimes")
被发送到表示方法引用(curried 函数)的闭包,而不是 ViewController
.
的实例
闭包没有名为updateTimes
的方法,导致异常:
unrecognized selector sent to instance
将初始值代码移动到一些实例上下文中,然后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
}
在我的ViewControllerclass中,我有一个函数:
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版本中(用Swift3.1/Xcode8.3.3测试),上面的代码不会报错,但是self
是解释为在 NSObjectProtocol
中声明的 self()
方法的方法引用。因此,Selector("updateTimes")
被发送到表示方法引用(curried 函数)的闭包,而不是 ViewController
.
闭包没有名为updateTimes
的方法,导致异常:
unrecognized selector sent to instance
将初始值代码移动到一些实例上下文中,然后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
}