本文介绍在 Swift 中 使用 KVO 时,一些需要注意的事项,下面截取了两段我自己在项目中使用的代码。
self.timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self,
selector: "moveText", userInfo: nil, repeats: true)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "appEnterForeground", name: nil, object: nil)
第一个是第一个定时器(NSTimer),第二个是一个页面的监听事件。即,让程序不断地观察现在的『某个状态』,当这个状态符合某个条件时,就去执行 Selector 中的代码。比如,我们的界面中有一个让用户输入年龄的 UITextField,然后我们可以观察(监听),当发现用户在这里输入『0』时,我们就给一个提示:『年龄至少为1』。
简单介绍完毕,下面说注意事项。
<h3>1. private 关键字</h3>
最简单的使用 Selector 的情况,就是如上面所列出的,在 NSTimer 中写 selector 为 "moveText",然后我们在同一个文件中,再相应地写一个
func moveText(){
// Your Code
}
就可以了。
然而如果你想把它声明为一个 private func,即不希望其他文件调用这个函数,就会出现问题,通俗地讲:private 使得这个函数不能被『外部』调用,而 Selector 对它的调用,实际上就是一种『外部调用』。
【解决方案】
KVO 是基于 KVC 和动态派发技术(Dynamic Dispatch)的,Swift 为了效率禁用了 Objective-C 中有的动态派发。那么你把这个动态特性再加回来就可以了~
1.通过 @objc 关键字来使用动态特性
@objc private func moveText(){
// Your Code
}
2.通过 dynamic 关键字来让这个函数拥有与 OC 中动态调用时相同的运行时特性(@objc 足矣,这个一般用不上)
dynamic private func moveText(){
// Your Code
}
更多关于 dynamic 关键字的内容可以参考:http://swifter.tips/kvo/
<h3>2. class 关键字</h3>
如果你想把这个函数声明为 class func
class func moveText(){
// Your Code
}
则本文最开始的代码中的 target 应该由 self 换为 MyClass.self (假设这段代码写在名为 MyClass 的类中)
self.timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: MyClass.self,
selector: "moveText", userInfo: nil, repeats: true)
最后, 以上关键字是可以叠加使用的,如果你愿意,可以写成下面这样:
@objc private class func moveText(){
// Your Code
}
我在 StackOverFlow 中的回答,及其它相关:
http://stackoverflow.com/questions/28184350/4-questions-about-selectors-in-swift
如有谬误,欢迎在评论中指出。