web-dev-qa-db-ja.com

swift)で親ViewControllerにイベントをディスパッチします

私はAS3のバックグラウンドから来ているので、AS3で何をしようとしているのかを簡単に説明できるかもしれません。 UIViewController(root)があり、その中にContainerViewがあります。コンテナビューのUIViewControllerはUIViewController(root)の子であるという印象を受けています。子ビューコントローラー(コンテナービュー)でボタンを押して、そのイベントを親(ルートUIViewController)にバブルしたいと思います。 AS3ではこのようなものがあります

ルートクラスは子クラスを作成します

var childClass = new ChildClass()

childClass.addEventListener("buttonWasPressed", callThisFunction);

private function callThisFunciton(e:Event):void
{
// move the child view
TweenLite.to(childClass,1,{x:100});

}

そして、子クラスには、このイベントをデプロイして親にバブルアップするボタン関数があります。

dispatchEvent(new Event("buttonWasPressed", true));

ルートを取得する方法がわからないVCそのイベントをリッスンしています。containerViewを使用しているため、その子へのアウトレットを設定する方法がわかりません= VCそして子供がしていることを聞いてください。IBからVCへのドラッグを制御できますが、それはコンテナビューを表すUIViewのアウトレットを作成しただけです。テキストを印刷すると、子ViewControllerが親VCの前に最初にインスタンス化されていることがわかります。

この投稿は正しい方向を向いていると思います。 https://craiggrummitt.wordpress.com/2014/07/14/communication-between-objects-in-objective-c-and-Swift-compared-with-actionscript-part-5/

しかし、エラーが発生します。おそらく、コンテナビュー内にある親VCから子VCへの接続方法がわからないためです。 。私は周りを見回しましたが、このトピックに関する多くの情報を見つけることができないようです。

助けてくれてありがとう!

13
icekomo

2つの方法があります:

1)デリゲートプロトコルを使用する(推奨)

a)子で、デリゲートプロトコルを作成し、子VC)にデリゲートを保持するオプションのプロパティを作成します。

_protocol ChildViewControllerDelegate {

}

class ChildViewController: UIViewController {

    var delegate:ChildViewControllerDelegate?
}
_

b)デリゲートプロトコルで、ボタンが押されたときに呼び出されるメソッドを作成し、デリゲートでこのメソッドを呼び出す子にbuttonWasPressed()メソッドを実装します。 (このメソッドをストーリーボードのボタンに接続することをお勧めします)

_protocol ChildViewControllerDelegate {
    func childViewControllerDidPressButton(childViewController:ChildViewController)
}

class ChildViewController: UIViewController {

    var delegate:ChildViewControllerDelegate?

    @IBOutlet weak var button: UIButton!

    @IBAction func buttonWasPressed(sender: AnyObject) {
        self.delegate?.childViewControllerDidPressButton(self)
    }
}
_

c)親ViewControllerを子プロトコルに準拠させる

_class ParentViewController: UIViewController, ChildViewControllerDelegate {

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}
_

c)子が親に埋め込まれると、埋め込みセグエと呼ばれる特別な種類のセグエが実行されます。ストーリーボードで確認できます。これは、子と親を結ぶ線です。

shows the embed segue selected

ストーリーボードのそのセグエに識別子を追加します。

shows the settings for embed segue, with the custom identifier set

そして、親ViewControllerでの定数:

_struct Constants {
    static let embedSegue = "embedSegue"
}

class ParentViewController: UIViewController, ChildViewControllerDelegate {

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}
_

d)次に、親View Controllerで、prepareForSegue()メソッドをオーバーライドし、_segue.identifier_が識別子として設定したものと一致するかどうかを確認します。含まれている場合は、_segue.destinationViewController_を介して子ViewControllerへの参照を取得できます。これを子ViewControllerとしてキャストすると、親をそのデリゲートに設定できます。

_struct Constants {
    static let embedSegue = "embedSegue"
}

class ParentViewController: UIViewController, ChildViewControllerDelegate {

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == Constants.embedSegue {
            let childViewController = segue.destinationViewController as ChildViewController
            childViewController.delegate = self
        }
    }

    func childViewControllerDidPressButton(childViewController: ChildViewController) {
        // Do fun handling of child button presses!
    }
}
_

e)勝つ!

2)NSNotificationとNSNotificationCenterを使用します

これらはActionScriptイベントに似ていると考えることができますが、ASのようにビュー階層を介して自動的にバブルアップすることはありません。代わりに、通知はNSNotificationCenterを介してグローバルにディスパッチされます。 1つの特定のイベントをリッスンする必要があるオブジェクトが複数ある場合にのみ、これを使用することを好みます。

NSNotificationおよびNSNotificationCenterの詳細については、次を参照してください: https://developer.Apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class /

33
BTSmith

または、静的変数を使用することもできます。これはおそらく最も簡単な方法です。

class ParentViewController: UIViewController {

    static var instance:ParentViewController?

    override func awakeFromNib() {
        self.dynamicType.instance = self
    }

    func parentFunction() {
        print("called \(#function) in \(self.dynamicType)")
    }
}

class ChildViewController: UIViewController {
    func childFunction() {
        ParentViewController.instance?.parentFunction()
    }

    override func viewDidAppear(_ animated: Bool) {
        childFunction()
    }
}
5
pravdomil