1

クラスの init から別のメソッドにクロージャーを動的にアタッチしたいと思います。たとえば、拡張機能を追加して、イベントUIViewControllerにコードを挿入できるようにします。viewDidLoad以下のようなことを試しましたが、うまくいきません。

class BaseViewController: UIViewController, MyProtocol {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // Setup and bind
        configure()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Call MyProtocol.myDidLoad but not explicitly!
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        // Call viewWillAppear but not explicitly!
    }

}

protocol MyProtocol { }

extension MyProtocol where Self: UIViewController {

    func configure() {
        // Something like below isn't possible???
        self.viewDidLoad += myDidLoad
        self.viewWillAppear += myWillAppear
    }

    func myDidLoad() {
        // Something
    }

    func myWillAppear() {
        // Something
    }
}

からプロトコル関数を明示的に呼び出すことなく、これを達成することは可能UIViewControllerですか? すべてのクラスを調べて、各関数のプロトコル関数を呼び出す必要はありません。これは退屈で冗長なコードであり、見落とされがちです。もっとエレガントな方法はありますか?

アップデート:

以下は、制限を考慮して私が考えることができる唯一の方法ですが、構成よりも継承を使用しており、プロトコル拡張関数を明示的に呼び出す必要があります。これは私がやりたいことではありません:

class FirstViewController: BaseViewController {

}

class BaseViewController: UIViewController, MyProtocol, MyProtocol2, MyProtocol3 {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // Configure protocols
        configure(self as MyProtocol)
        configure(self as MyProtocol2)
        configure(self as MyProtocol3)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load protocols
        viewDidLoad(self as MyProtocol)
        viewDidLoad(self as MyProtocol2)
        viewDidLoad(self as MyProtocol3)
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        // Prerender protocols
        viewWillAppear(self as MyProtocol)
        viewWillAppear(self as MyProtocol2)
        viewWillAppear(self as MyProtocol3)
    }

}

protocol MyProtocol { }

extension MyProtocol where Self: UIViewController {

    func configure(delegate: MyProtocol) {
        print("MyProtocol.configure")
    }

    func viewDidLoad(delegate: MyProtocol) {
        print("MyProtocol.viewDidLoad")
    }

    func viewWillAppear(delegate: MyProtocol) {
        print("MyProtocol.viewWillAppear")
    }
}

protocol MyProtocol2 { }

extension MyProtocol2 where Self: UIViewController {

    func configure(delegate: MyProtocol2) {
        print("MyProtocol2.configure")
    }

    func viewDidLoad(delegate: MyProtocol2) {
        print("MyProtocol2.viewDidLoad")
    }

    func viewWillAppear(delegate: MyProtocol2) {
        print("MyProtocol2.viewWillAppear")
    }
}

protocol MyProtocol3 { }

extension MyProtocol3 where Self: UIViewController {

    func configure(delegate: MyProtocol3) {
        print("MyProtocol3.configure")
    }

    func viewDidLoad(delegate: MyProtocol3) {
        print("MyProtocol3.viewDidLoad")
    }

    func viewWillAppear(delegate: MyProtocol3) {
        print("MyProtocol3.viewWillAppear")
    }
}

//Output:
//MyProtocol.configure
//MyProtocol2.configure
//MyProtocol3.configure
//MyProtocol.viewDidLoad
//MyProtocol2.viewDidLoad
//MyProtocol3.viewDidLoad
//MyProtocol.viewWillAppear
//MyProtocol2.viewWillAppear
//MyProtocol3.viewWillAppear

これは、プロトコル指向プログラミングの目的全体を無効にします。iOS 開発の範囲内で作業しているときに Swift が処理できるエレガントなアプローチはありますか、またはこの場合 POP は機能しませんか?

4

1 に答える 1

4

Swift と Objective-C はどちらも単一継承言語であるため、やりたいことは不可能です。

拡張機能はメソッドを追加することしかできず、メソッドをオーバーライドすることはできません。既存のクラスのメソッドをオーバーライドできるのは、サブクラスだけです。複数の拡張機能が同じメソッドをオーバーライドした場合を考えてみましょう。どのメソッドを呼び出す必要がありますか? 全部ですか?ある場合、どの順番で?ダイヤモンドの問題を参照してください

最も簡単な方法は、必要な機能を提供する UIViewController サブクラスを作成することです。プログラマーがプロトコルに準拠しているが正しいスーパークラスをサブクラス化していないクラスを作成することは可能ですが、クラスとプロトコルが同じ行に入力されていることを考えると、それはかなりばかげたエラーになります。

于 2016-02-26T22:29:04.023 に答える