2017-07-13 49 views
3

語言的可選功能:迅捷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是一個可選功能,如果任何一個發送帶有鑰匙NSNotification.Name(rawValue: "UltimateNotificationKeyLOL")的應用程序會崩潰,因爲我還沒有實現foo又一個Notification。所以在這種情況下,上面的代碼會導致崩潰。

但是,如果我這樣做

class GodzillaViewController: UIViewController { 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     self.listenToFoo() 
    } 
} 

extension GodzillaViewController: SomeProtocol { 
    func foo(_ notification: Notification) { 
     print("lol") 
    } 
} 

因爲foo(_:)沒有崩潰創建不是可有可無的了。

:此代碼是不可能的#selector(self.foo?(_:))

問題:是否有可能有一個選擇調用的可選功能沒有崩潰的應用程序?

回答

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) 
     } 
    } 
} 

正如你所看到的,做它像這樣有很多好處:

  1. 你有斯威夫特只代碼(no @objc)
  2. 通過添加foo的默認實現,您使該功能成爲可選項。
  3. 您的通知仍然可以調用foo沒有崩潰,因爲它會在必要時去的默認實現
  4. ,你甚至可以添加一些代碼的默認方法,如果你仍然想要做的事!

UPDATE

您可以在我用一個使用了閉相反,原因是#selector仍需要功能暴露於@objc不同addObserver功能listenToFoo()功能看和關閉不:

func addObserver(forName name:NSNotification.Name ?, object obj:Any ?, queue:OperationQueue?,使用塊:@escaping(通知) - >無效) - > NSObjectProtocol

+0

@Hamish是正確的,你不能誰不暴露於對象 - –

+0

函數使用通知中心@Hamish你說得對,我更新了使用不需要@objc的不同'addObserver'函數的答案!謝謝 – Thomas

+1

@ZonilyJame'#選擇器'這樣做的方式是需要一種方法暴露給ObjC。當然還有其他的可能性,比如我改變它的那個,或者如果你真的想使用選擇器出於某種原因,你應該看看Swift變體,它可以像這樣工作,而不是'Selector(「foo(_ :)」)' – Thomas

相關問題