Ios 如何使用选择器和NotificationCenter调用可选函数
语言:Swift 3 IDE:XCode 8.3.2(8E2002) 我有一个带有可选功能的协议Ios 如何使用选择器和NotificationCenter调用可选函数,ios,swift,selector,swift-protocols,Ios,Swift,Selector,Swift Protocols,语言: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, sele
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
是一个可选函数,如果任何人使用键NSNotification.Name(rawValue:“UltimateNotificationKeyLOL”)
发送通知,应用程序将崩溃,因为我还没有实现foo
。因此,在这种情况下,上述代码将导致崩溃
但是如果我这样做
class GodzillaViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.listenToFoo()
}
}
extension GodzillaViewController: SomeProtocol {
func foo(_ notification: Notification) {
print("lol")
}
}
由于foo(:)
不再是可选的,因此不会创建崩溃
同样:此代码不可能#选择器(self.foo?(:)
问题:有没有可能让选择器调用一个可选函数而不使应用程序崩溃?如果我在你那里,我会像这样制定一个完整的swift协议:
// 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)
}
}
}
如您所见,这样做有多重好处:
您只有Swift代码(无@objc)
通过添加foo
的默认实现,您使函数成为可选的李>
您的通知仍然可以调用foo
,而不会崩溃,因为它将在必要时转到默认实现
如果您仍然想做一些事情,您甚至可以向默认方法添加一些代码李>
更新
您可以在listenToFoo()
函数中看到,我使用了一个不同的addObserver
函数,该函数使用了闭包,原因是#selector仍然要求将函数公开给@objc,而闭包没有:
func addObserver(forName名称:NSNotification.name?,对象对象对象:Any?,队列:OperationQueue?,使用块:@escaping(Notification)->Void)->NSObjectProtocol
@Hamish是正确的,您不能对未暴露于Obj的函数使用NotificationCenter-C@Hamish你说得对,我更新了答案,使用了一个不需要@objc的不同的addObserver
函数!Thanks@ZonilyJame执行此操作的#选择器方法需要将方法公开给ObjC。当然还有其他的可能性,比如我把它改成的,或者如果你真的想出于某种原因使用选择器,你应该看看Swift变体,它的工作原理是这样的Selector(“foo(:)”)
ohhh,根据你的代码,我找到了一个我想去的解决方案。我还认为,addObserver(……block:)
仅在上面的iOS 10/9中受支持,看起来他们改变了它。但这也是一个很好的实现,它没有告诉我如何使用@objc