2015-11-25 16 views
11

メニューバーボタンを持つビューコントローラのセットがあります。私はそれらのviewControllerが採用するためのプロトコルを作成しました。また、プロトコルを拡張してデフォルトの機能を追加しました。プロトコル拡張でターゲットアクションを追加できません

マイプロトコルは

protocol CenterViewControllerProtocol: class { 

    var containerDelegate: ContainerViewControllerProtocol? { get set } 

    func setupMenuBarButton() 
} 

、のように見えると、拡張子がそうのように見える、

extension CenterViewControllerProtocol where Self: UIViewController { 

    func setupMenuBarButton() { 
     let barButton = UIBarButtonItem(title: "Menu", style: .Done, target: self, action: "menuTapped") 
     navigationItem.leftBarButtonItem = barButton 
    } 

    func menuTapped() { 
     containerDelegate?.toggleSideMenu() 
    } 
} 

私のViewControllerがプロトコルを採用している -

class MapViewController: UIViewController, CenterViewControllerProtocol { 

    weak var containerDelegate: ContainerViewControllerProtocol? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     setupMenuBarButton() 
    } 
} 

私は表示するボタンを得ましたうまくいけば、それをクリックすると、アプリがクラッシュする

[AppName.MapViewController menuTapped]: unrecognized selector sent to instance 0x7fb8fb6ae650 

このメソッドをViewController内に実装すると、正常に動作します。しかし、私はプロトコルに準拠しているすべてのviewControllerでコードを複製しています。

ここで間違っていることは何ですか? ありがとうございます。

答えて

0

プロトコル拡張を使用しているようですが、現時点ではサポートされていません。 fluidsonic's答えhereによると:いずれの場合で

あなたは、セレクタ経由で使用する予定のすべての機能は、動的または@objcでマークする必要があります。この結果、このコンテキストで@objcを使用できないというエラーが発生した場合、何をしようとしているのかはサポートされていません」。

この例では、

0

これはコンパイルされますが、Xcode7.3 Betaでもクラッシュするので、最終的にはアクションのターゲットとして醜いスーパークラスを使用する必要があります。このクラスは、それはあなたと私が避けようとしているものだと思います。

0

これは古い質問ですが、私も同じ問題に遭遇して来ました。完璧ではない可能性がある解決策がありますが、私が考えることができる唯一の方法です。

明らかにSwift 3でも、あなたのプロトコル拡張にtarget-actionを設定することはできません。しかし、プロトコルに準拠するすべてのViewControllerでfunc menuTapped()メソッドを実装せずに、目的の機能を実現できます。

最初のこの

extension CenterViewControllerProtocol where Self: UIViewController { 

     func setupMenuBarButton() { 
      let barButton = UIBarButtonItem(title: "Menu", style: .Done, target: self, action: "menuTappedInVC") 
      navigationItem.leftBarButtonItem = barButton 
     } 

     func menuTapped() { 
      containerDelegate?.toggleSideMenu() 
     } 
    } 

お知らせは現在、ボタンのアクションは、あなたの拡張子ではなく、「menuTapped」の「menuTappedInVC」であるように今、あなたの拡張子を変更するあなたのプロトコルに

protocol CenterViewControllerProtocol: class { 

    var containerDelegate: ContainerViewControllerProtocol? { get set } 

    //implemented in extension 
    func setupMenuBarButton() 
    func menuTapped() 

    //must implement in your VC 
    func menuTappedInVC() 
} 

を新しいメソッドを追加してみましょう。 CenterViewControllerProtocolに準拠するすべてのViewControllerは、このメソッドを実装する必要があります。あなたのViewControllerで

class MapViewController: UIViewController, CenterViewControllerProtocol { 

    weak var containerDelegate: ContainerViewControllerProtocol? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     setupMenuBarButton() 
    } 

    func menuTappedInVC() 
    { 
     self.menuTapped() 
    } 

あなたがしなければならないのは、あなたのVCでmenuTappedInVC()メソッドを実装し、それがあなたのターゲット・アクションメソッドになりますです。その中で、あなたのプロトコル拡張で既に実装されているmenuTappedにそのタスクを委譲することができます。

関連する問題