让我们考虑以下代码:
protocol A {
func doA()
}
extension A {
func registerForNotification() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardDidShow:"), name: UIKeyboardDidShowNotification, object: nil)
}
func keyboardDidShow(notification: NSNotification) {
}
}
现在来看一个实现A的UIViewController子类:
class AController: UIViewController, A {
override func viewDidLoad() {
super.viewDidLoad()
self.registerForNotification()
triggerKeyboard()
}
func triggerKeyboard() {
// Some code that make key board appear
}
func doA() {
}
}
但令人惊讶的是,它崩溃并出现错误:
键盘ID显示:]:发送到示例0x7fc97adc3c60的选择器无法识别
那么我应该在视图控制器中实现观察器吗?它不能留在扩展中吗?
下面的事情已经试过了。
使A成为一个类协议。将keyboardDidShow添加到协议本身作为签名。
protocol A:class {
func doA()
func keyboardDidShow(notification: NSNotification)
}
5条答案
按热度按时间xe55xuns1#
我通过实现
NSNotificationCenter
的较新的- addObserverForName:object:queue:usingBlock:
方法并直接调用该方法解决了一个类似的问题。此示例将导致在协议扩展中调用
keyboardDidShow
。vjrehmav2#
除了James Paolantonio的答案之外,
unregisterForNotification
方法也可以使用关联对象来实现。eeq64g8w3#
要避免崩溃,请在使用该协议的Swift类中实现观察器方法。
实现必须在Swift类本身中,而不仅仅是在协议扩展中,因为选择器总是引用Objective-C方法,而协议扩展中的函数不能作为Objective-C选择器使用。然而,如果Swift类继承自Objective-C类,那么Swift类中的方法就可以作为Objective-C选择器使用
如果Swift类继承自Objective-C类,则该类中的所有方法和属性都可用作Objective-C选择器。
此外,在Xcode 7.1中,在
addObserver
调用中将self
指定为观察者时,必须将其向下转换为AnyObject
。1wnzp6jl4#
在Swift中使用选择器要求你的具体类必须继承自NSObject。要在协议扩展中强制执行这一点,你应该使用
where
。例如:xxhby3vn5#
我用
NSObjectProtocol
解决了这个问题,如下所示: