Search code examples
swiftuicontainerview

Share Data Between View Controller and Container View


I have a view controller that has a segue to a second view controller, and I passed some data to the second one in prepare for segue. The problem is: the second view controller has a container view which I need to share that data with. I tried using prepare for segue but it didn't work in this case.

Update:

View Controller code:

class ViewController: UITableViewController, ContainerViewDelegate {

   var myContainerView = ContainerView()
   var id: String!

   override func viewDidLoad() {
        super.viewDidLoad()
        id = "123"
        myContainerView.delegate = self
   }

   func initialize() -> String {
        return id
   }
}

Container view code:

protocol ContainerViewDelegate {
   func initialize() -> String
}

class ContainerView: UICollectionViewController {

   var delegate: ContainerViewDelegate!
   var id: String!
   override func viewDidLoad() {
       super.viewDidLoad()
       id = delegate.initialize()
       print(id)
   }
}

I get error: fatal error: unexpectedly found nil while unwrapping an Optional value at the line: id = delegate.initialize()


Solution

  • You are on the right track to setup the delegate.

    In Storyboard:

    • create a Segue of type Embed Segue from the ContainerView to the ViewController to embed.
    • Select the segue and set a Identifier.

    In Code, in prepareForSegue():

    • Set the myContainerView propert
    • Set the delegate

      class ViewController: UITableViewController, ContainerViewDelegate {
          var myContainerView:ContainerView? // we do initialize it in prepareForSegue()
          var id: String!
      
          override func viewDidLoad() {
              super.viewDidLoad()
              id = "123"
              // myContainerView.delegate = self //myContainerView is nil here. We set it in prepareForSegue
          }
      
          func initialize() -> String {
              return id
          }
      
          let embedSegueID = "the identifier you set to your embed segue in Storyboard"
      
          override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
              if (segue.identifier == embedSegueID) {
                  let dvc = segue.destination as! ContainerView
                  // Now you have a pointer to EmbeddedViewController.
                  // You can save the reference to it, or pass data to it.
                  myContainerView = dvc
                  myContainerView.delegate = self
              }
              print(segue.identifier)
          }
      }
      

    If you want to pass data from your ViewController to AnotherViewController which is embedded in your destinationViewController (how I understand your question), I would:

    • pass it to destinationViewController as in the example above (prepareForSegue)
    • than pass it to AnotherViewController in viewWillAppear() from within destinationViewController.

    In this case, how I understand your usecase, you do not need the delegate and can remove all delegate related code (initialize, the ContainerViewDelegate protocol, the property var delegate: ContainerViewDelegate! and all calls to it.