How to transfer data between Parent and Child View Controllers

3.8k views Asked by At

I have tried looking at answers on similar questions to this, but I am not particularly experienced and have had trouble following them, so any help would be much appreciated! My situation is as follows: when I press a button in my Parent ViewController, the following code is used to call a Child ViewController (by the way, the Child is actually a TableViewController, but it seems to work fine "thinking" it's a normal ViewController?):

controller = (storyboard?.instantiateViewController(withIdentifier: "People"))
addChildViewController(controller!)
controller?.view.frame = CGRect(x: 10, y: 200, width: 394, height: 300)
self.view.addSubview((controller?.view)!)
controller?.didMove(toParentViewController: self)

What I would then like is to transfer an array from the Parent to the Child, where it will be used as the TableView's data?

Secondly, when I select a cell from the Child's TableView, I would like the relevant information to be sent to the Parent, and for the Child to disappear.
In case it is of interest, I have managed to close the Child under different circumstances (when a click occurs in the Parent while the Child is displayed) using the following:

controller?.willMove(toParentViewController: nil)
controller?.view.removeFromSuperview()
controller?.removeFromParentViewController()

I would really appreciate any advice, even if it's a link to something which would help!

3

There are 3 answers

0
Usman Javed On

You can pass value from Parent to Child Controller like this

controller = (storyboard?.instantiateViewController(withIdentifier: "People"))
    addChildViewController(controller!)
    controller?.view.frame = CGRect(x: 10, y: 200, width: 394, height: 300)
    controller.tableDataSource = // Pass your required value to child controller
    self.view.addSubview((controller?.view)!)
    controller?.didMove(toParentViewController: self)

Now you want to transfer back your select value to Parent view controller. For this purpose your have a create a Delegate in ChildController like

@protocol ChildControllerDelegate : class {
    func selectedValue(Value : String)
}

After that make a variable of that delegate in ChildController like this

weak var delegate : ChildControllerDelegate?

and when in rowDidSelect method add following code

if(delegate != nil) {
   delegate.selectedValue(Value :"Your selected value")
}

Now step when you are going to show ChildController from ParentController at that time you have to set that delegate object to ParentController like this

controller = (storyboard?.instantiateViewController(withIdentifier: "People"))
    addChildViewController(controller!)
    controller?.view.frame = CGRect(x: 10, y: 200, width: 394, height: 300)
    controller.delegate = self
    self.view.addSubview((controller?.view)!)
    controller?.didMove(toParentViewController: self)

and after that just implement the delegate method in ParentController like that

func selectedValue(Value : String) {
   // you select val 
}
1
Rob On

You can:

  • Cast the controller to the appropriate class for the child view controller (I'm using ChildViewController below, but hopefully you have a more descriptive name); and

  • Pass the array (which I guessed you might have called people, but use whatever your array names are in these two respective view controllers) from the current view controller (the parent) to this new child view controller.

Thus:

let child = storyboard!.instantiateViewController(withIdentifier: "People") as! ChildViewController
addChildViewController(child)
child.people = people
child.view.frame = ...
view.addSubview(child.view)
child.didMove(toParentViewController: self)

Personally, I wouldn't hard code the child coordinates like you did in your original question. I'd set translatesAutoresizingMaskIntoConstraints to false and then add the appropriate leading/trailing/top/bottom constraints, but that's up to you. It was just too painful to see hardcoded coordinates in your example.

0
Dixit Akabari On

Try This.

First Create Public Method For Add And Remove childVC.

For Add childVC.

public class func openChildViewController(parentVC:UIViewController, with childVC:UIViewController){

        parentVC.addChildViewController(childVC)
        childVC.view.frame = parentVC.view.frame
        parentVC.view.addSubview(childVC.view)
        parentVC.didMove(toParentViewController: childVC)
    }

For Remove childVC.

   public class func removeChildViewController(childVC:UIViewController){

        childVC.willMove(toParentViewController: nil)
        childVC.view.removeFromSuperview()
        childVC.removeFromParentViewController()
    }

Use Above Method.

1.ParentVC.swift

class ParentVC: UIViewController , ChildVCDelegate  {

     var arrType = NSMutableArray()

    //add ChildVC
    @IBAction func btnAddChildVC(_ sender: UIButton) {
        let ChildVC = self.storyboard?.instantiateViewController(withIdentifier: "ChildVC") as! ChildVC
        PickerVC.arrPass = arrType //for data passing create any object in ChildVC for ex. arrPass is NSMutableArray
        ChildVC.delegate = self
        openChildViewController(parentVC: self, with: ChildVC)
    }

     // MARK: ChildVC Delegate
   func SetSelectedPickerValue(strSelectOption: String) {
                print(strSelectOption)
        }
    }

}

2.ChildVC.swift

class ChildVC: UIViewController{

    // MARK: Variable for ParentVCData Passing
     var arrPass = NSMutableArray()

    override func viewWillAppear(_ animated: Bool) {
        print(arrPass)
    }

    //Remove ChildVC
    @IBAction func btnRemoveChildVC(_ sender: UIButton) {
        self.delegate?.SetSelectedPickerValue!(strSelectOption: “any String you pass ChildVC To ParentVC”)
        removeChildViewController(childVC: self)
    }
}
// MARK: Create Delegate Method
@objc protocol ChildVCDelegate{
     @objc optional func SetSelectedPickerValue(strSelectOption:String)
}