30168
UITabBarController の異なるタブ間で関数を呼び出す方法について質問です。  
UITabBarController で FirstViewController, SecondViewController
を作成したのですが、FirstView のボタンを押すことで SecondView の関数を呼び出すにはどうすれば良いのでしょうか。

protocol を介して delegate を設定してやることによってできそうなのですが、以下のようなコードを実行してもうまく出力されませんでした。

FirstViewController.swift

```

    import UIKit
    
    class FirstViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            //print("first view generated")
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        weak var delegate: Del?
        @IBAction func say(sender: AnyObject) {
            //print("button pushed")
            self.delegate?.sayHello()
        }
    }
    
    
    @objc protocol Del {
        func sayHello() -> Void
    }
    
```

SecondViewController.swift

```

    import UIKit
    
    class SecondViewController: UIViewController, Del {
    
        override func viewDidLoad() {
        super.viewDidLoad()
        //print("second view generated")
        //self.sayHello()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
        func sayHello() -> Void{
            print("hello world");
        }
    }
    
```

（tab を切り替えて first, second ともに生成したのちにボタンを押してもコンソールに"hello world"が出力されない。）

delegate を扱っているコードを見ると SecondView の中で FirstView をインスタンス化して delegate を self
に指定すればよさそうなのですが、この場合どのようにすればよいのでしょうか。

宜しくお願いします。
CC BY-SA 3.0
2016-11-06T09:48:44.467
30129
2016-11-06T23:39:57.403
2016-11-06T09:54:40.123
19452
19452
question
swift xcode
Swift における Tab 間での関数の呼び出しについて
`UITabBarController`のタブを固定している（動的にタブを変更しない）ことを前提にしますと、`UITabBarController`のプロパティ`viewControllers`を使って、`FirstViewController`から`SecondViewController`をたどっていくことができますので、Delegateの出番は必要ありません。`UIViewController`のプロパティ`tabBarController`で、`UITabBarController`のインスタンスを取得し、`UITabBarController`のプロパティ`viewControllers`から、`SecondViewController`のインスタンスを取得します。

_FirstViewController_

```

    @IBAction func say(sender: AnyObject) {
        if let controller = tabBarController?.viewControllers?[1] as? SecondViewController {
            controller.sayHello()
        }
    }
    
```

ここで注意していただきたいのは、`UITabBarController`のインスタンスをロードした直後は、Viewがロードされているのは、最初の（いちばん左のタブの）View
Controllerだけだという点です。つまり、`SecondViewController`のインスタンスは生成されていますが、`loadView`メソッドが実行されていないので、ラベルなどのViewにアクセスすると、`nil`が返ってきます。

```

    @IBAction func say(sender: AnyObject) {
        if let controller = tabBarController?.viewControllers?[1] as? SecondViewController {
            controller.loadViewIfNeeded()
            controller.label?.text = "Hello"
        }
    }
    
```

ラベルなどのViewにアクセスする場合は、上のサンプルのように、`loadViewIfNeeded()`メソッドを呼んで、Viewをロードしておきます。
CC BY-SA 3.0
2016-11-06T22:25:15.857
30168
2016-11-06T23:39:57.403
2016-11-06T23:39:57.403
18540
18540
30129
answer