语言:Swift 3
IDE :XCode 8.3.2(8E2002)
我有一个带有可选功能foo
@objc protocol SomeProtocol {
@objc optional func foo(_ notification: Notification)
}
extension SomeProtocol {
func listenToFoo() {
NotificationCenter.default.addObserver(self, selector: #selector(self.foo(_:)), name: NSNotification.Name(rawValue: "UltimateNotificationKeyLOL"), object: nil)
}
}
如果我将此代码扩展为类,请说UIViewController
。
class CrashingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.listenToFoo()
}
}
extension CrashingViewController: SomeProtocol { }
现在出现了问题,因为foo
是一个可选函数,如果任何人发送带有密钥Notification
的{{1}},应用程序将崩溃,因为我没有实现{{ 1}}。所以在这种情况下,上面的代码会导致崩溃。
但是,如果我这样做
NSNotification.Name(rawValue: "UltimateNotificationKeyLOL")
由于foo
不再是可选项,因此不会创建崩溃。
:此代码无法class GodzillaViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.listenToFoo()
}
}
extension GodzillaViewController: SomeProtocol {
func foo(_ notification: Notification) {
print("lol")
}
}
问题:是否可以让选择器调用可选功能而不会使应用程序崩溃?
答案 0 :(得分:4)
如果我在哪里,我会像这样制定一个完整的协议:
// Protocol declaration
protocol SomeProtocol {
func foo(_ notification: Notification)
}
// Provide default implementation for optional methods of SomeProtocol
extension SomeProtocol {
func foo(_ notification: Notification) {}
}
// Extend SomeProtocol with additional methods
extension SomeProtocol {
func listenToFoo() {
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "UltimateNotificationKeyLOL"), object: nil, queue: nil) { (notification) in
self.foo(notification)
}
}
}
正如您所看到的,这样做有很多好处:
foo
的默认实现,您可以使该函数成为可选项。 foo
而不会崩溃,因为如果有必要,它会转到默认实现<强>更新强>
你可以在listenToFoo()
函数中看到我使用了另一个使用闭包的addObserver
函数,原因是#selector仍然需要将函数暴露给@objc和闭包不:
func addObserver(forName name:NSNotification.Name ?, object obj:Any ?, queue:OperationQueue ?, using block:@escaping(Notification) - &gt; void) - &gt; NSObjectProtocol