简体   繁体   中英

How can I pass data from a parent view controller to an embedded view controller in Swift?

I have a view controller embedded in another VC. I would like to get the value of a variable from the main VC inside the embedded one. Specifically, I would like to change the text of label2 based on the value of label1.

I tried with "prepareForSegue", but it seems it's not triggered for embedded view controllers. I tried to isolate the problem in a test project:

在此处输入图片说明

Code for main VC:

class MyViewController: UIViewController {
    @IBOutlet weak var label1: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        label1.text = "Hello"
    }
}

Code for embedded VC:

class EmbeddedVC: UIViewController {
    @IBOutlet weak var label2: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
 }

Thanks for your help :)

First of all you can't set directly EmbeddedVC's lable2.text In prepareForSegue

because call sequence following below

  1. MainVC's prepareForSeque this time EmbeddedVC's label2 is nil
  2. EmbeddedVC's viewDidLoad called then label2 loaded
  3. MainVC's viewDidLoad called then label1 loaded

so if you assign MainVC's label1.text to EmbeddedVC's label2.text in prepareForSeque both label1 and label2 are nil so did not work

There are two way to solve this question

First Solution MainViewController has EmbeddedVC and when MainVC's viewDidLoad called, assign label1.text to embeddedVC.label2.text

class MyViewController: UIViewController {
    @IBOutlet weak var label1: UILabel!
    var embeddedVC: EmbeddedViewController? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        label1.text = "Hello"
        embeddedVC?.label2.text = label1.text
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let embeddedVC = segue.destination as? EmbeddedViewController {
            self.embeddedVC = embeddedVC
        }
    }
}

class EmbeddedViewController: UIViewController {
    @IBOutlet weak var label2: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Second Solution, use protocol and get MainVC's label text when viewWillAppear or viewDidAppear (later viewDidLoad called)

protocol EmbeddedVCDelegate: class {
    func labelText() -> String?
}

class MyViewController: UIViewController, EmbeddedVCDelegate {
    @IBOutlet weak var label1: UILabel!

    // MARK: EmbeddedVCDelegate
    func labelText() -> String? {
        return label1.text
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        label1.text = "Hello"
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let embeddedVC = segue.destination as? EmbeddedViewController {
            embeddedVC.delegate = self
        }
    }
}

class EmbeddedViewController: UIViewController {
    @IBOutlet weak var label2: UILabel!
    weak var delegate: EmbeddedVCDelegate? = nil
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        label2.text = delegate?.labelText()
    }
}

A way to achiеve this is to get the child view controller instance in the parent's viewDidLoad. It appears that the parent's viewDidLoad: gets called after the child's viewDidLoad:, which means the label is already created in the child's view.

override func viewDidLoad() {
    super.viewDidLoad()

    if let childVC = self.childViewControllers.first as? ChildVC {
        childVC.someLabel.text = "I'm here. Aye-aye."
    }   
}

You should try to use prepareForSegue like this:

if segue.identifier == "identifier" {
        guard let destinationViewController = segue.destination as? VC2 else { return }

        destinationViewController.label2.text = mytext
    }

Where the segue identifier you assign in storyboard

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM