Какой самый простой способ передачи данных между двумя одновременно отображаемыми контроллерами представления? - PullRequest
0 голосов
/ 18 декабря 2018

Я путаюсь, пытаясь передать данные между двумя контроллерами представления, которые отображаются на одном экране через представления контейнера.

Минимальный пример ниже - вид сверху (TopVC) имеет поле textInput.Когда я нажимаю кнопку, я хочу, чтобы на метке снизу (BottomVC) отображался введенный текст.Более того, я хочу, чтобы он передал сообщение TopVC и обновил метку topVC с сообщением «Успешно установлен нижний VC»

Настройка раскадровки

Screen Shot

Теперь я понятия не имею, ссылаться на контроллеры представления друг от друга в основном.

class TopViewController: UIViewController {

    @IBOutlet weak var textInput: UITextField!
    @IBOutlet weak var textOutput: UILabel!

    @IBAction func go(_ sender: UIButton) {
        // ??????????? 
    }

    override func viewDidLoad() {  
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.blue
    }

    func callMeBaby(greeting: String) {
        textOutput.text = greeting
    }
}

В заполнитель ????? я хочу поместить что-то, что в основном работает, как BottomVC.test (textInput.text, callmebaby) - но, очевидно, мне нужно поместитьв некотором дополнительном коде, чтобы «представить» два ViewControllers, и я не уверен, что делать.

class BottomViewController: UIViewController {

    @IBOutlet weak var textLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.yellow
    }

    func test(input: String, completion: (String) -> Void) {
        textLabel.text = input
        completion("Successfully contacted bottom VC")
    }
}

1 Ответ

0 голосов
/ 18 декабря 2018

Создание делегатов

Начните с создания делегатов для обоих ваших контейнерных ViewControllers.Не забудьте добавить : class.Если вы этого не сделаете, вы не сможете создать слабую переменную делегата:

protocol TopViewControllerDelegate: class {
    func sendMessage(_ string: String)
}
protocol BottomViewControllerDelegate: class {
    func sendMessage(_ string: String)
}

Теперь для каждого контейнера ViewController создайте слабую переменную делегата

class TopViewController: UIViewController {
    weak var delegate: TopViewControllerDelegate?
    ...
}

class BottomViewController: UIViewController {
    weak var delegate: BottomViewControllerDelegate?
    ...
}

затем для TopVC реализуйте делегат Bottom и для BottomVC Top.

extension TopViewController: BottomViewControllerDelegate {
    func sendMessage(_ string: String) {
        // do something
    }
}
extension BottomViewController: TopViewControllerDelegate {
    func sendMessage(_ string: String) {
        // do something
    }
}

Назначение делегатов

Ваши переходы между основным ViewController и контейнерами должны иметь свои собственные идентификаторы:EmbedTop, EmbedBottom.

Итак, в вашем WrapperViewController создайте переменную для вашего Top и Bottom ViewController и переопределите метод prepare(for:sender:) и внутри присвойте эти переменные

class WrapperViewController: UIViewController {

    var topVC: TopViewController?
    var bottomVC: BottomViewController?

    ...

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "EmbedTop" {
            topVC = segue.destination as! TopViewController
        } else if segue.identifier == "EmbedBottom" {
            bottomVC = segue.destination as! BottomViewController
        }
    }

}

, наконец, в viewDidAppear установите делегат TopVC какBottomVC и BottomVC как TopVC

override func viewDidAppear(_ animated: Bool) {
    topVC.delegate = bottomVC
    bottomVC.delegate = topVC
}

Теперь два ваших ViewController могут общаться друг с другом!: -)


Пример:

class BottomViewController: UIViewController {
    ...
    func speakToTop() {
        delegate?.sendMessage("Hi Top!")
    }
}
...