Jaisan Mathew
Jaisan Mathew

Reputation: 51

How to pass data from a 2nd VC to a VC inside a container in 1st VC in swift

I navigated to a VC (lets call is VC A) from a presented VC. In VC A, I have a container view and it has a VC (lets call is VC B). From VC B I presented another VC (lets call is VC C). From VC C I need to pass a few data back to VC B. How can I achieve the same.

I tried using protocol, but protocol is not hitting my VC B.Its hitting VC A only. But since I'm presenting VC C from VC B, I can't connect the delegate to self from VC A. So it's not working.

Again tried to save the data a global variable. And I tried to set the value to fields in viewWillAppear and ViewDidAppear in VC B.But due to some reason it's crashing every time. The crash is getting on the line

containerView.addSubview(remitController.view).


        let remitController = remitStoryboard.instantiateViewController(withIdentifier: "AddBeneficiaryController") as! AddBeneficiaryController
        addChildViewController(remitController)
        remitController.view.translatesAutoresizingMaskIntoConstraints = false

        containerView.addSubview(remitController.view)

        NSLayoutConstraint.activate([
            remitController.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            remitController.view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            remitController.view.topAnchor.constraint(equalTo: containerView.topAnchor),
            remitController.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
            ])

        remitController.didMove(toParentViewController: self)

Upvotes: 0

Views: 707

Answers (2)

Davidemi
Davidemi

Reputation: 1

I once encountered this problem when i tried using a container view for two view controllers depending on a flag. The solution i came up with was using delegates. I suggest you create a delegate to be implemented by VC B. At the point of instantiation of VC C you set the delegate. It should be declared as weak in VC C to avoid a retain cycle and memory leak. Call the delegate and send back your data from VC C back to B

protocol CtoBDelegate : class{
     func sendMyDataBack()//pass in any arguments also
}
class VC_C : UIViewController{
      weak var delegate : CtoBDelegate?
      override func viewDidLoad(){
      //do something
      delegate?.sendMyDataBack
   }
 }

 class VC_B : UIViewController{
      override func viewDidLoad(){
         let vc_C = //instantiate your view controller
         vc_C.delegate = self
         present(vc_C, animated : true)
    }
}

extension class VC_B : CtoBDelegate{
       func sendMyDataBack(){
          //do something with received data in VC_B

       }
   }

Another crude way you could implement a communication is using NotificationsCenter. Simply register your notifications in VC_B and set up a method to be called when a notification is received. Then post a notification from VC_C passing along whatever you need with the userinfo of the notification. If you opt for this do remember to remove the notification observer from VC_B when you are done to avoid a leak.

Upvotes: 0

PGDev
PGDev

Reputation: 24341

Use closure to solve the problem statement.

Create a closure in VCC controller,

class VCC: UIViewController {
    var handler: ((String)->())?

    func passDataToVCB() {
        handler?("This is sample data.")
    }
}

Call the handler whenever you want to pass data back to VCB along with the relevant data. I used String here.

Next, in VCB when you're presenting instance of VCC, set the handler value,

if let vcc = self.storyboard?.instantiateViewController(withIdentifier: "VCC") as? VCC {
    vcc.handler = {(value) in
        print(value)
    }

    //present vcc here...
    self.present(vcc, animated: true, completion: nil)
}

Upvotes: 1

Related Questions