如何在父视图控制器和子视图控制器之间传输数据

时间:2022-11-03 17:00:33

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?):

我已经尝试过对类似问题的答案,但我并不是特别有经验并且遇到麻烦,所以任何帮助都会非常感激!我的情况如下:当我在我的父ViewController中按下一个按钮时,下面的代码用于调用Child ViewController(顺便说一句,Child实际上是一个TableViewController,但似乎工作得很好“认为”这是正常的视图控制器)?

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?

我想要的是将一个数组从Parent转移到Child,它将用作TableView的数据?

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:

其次,当我从Child的TableView中选择一个单元格时,我希望将相关信息发送给Parent,并让Child消失。如果感兴趣的话,我设法在不同的情况下(当显示Child时在Parent中发生点击时)关闭Child,使用以下内容:

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 个解决方案

#1


1  

You can pass value from Parent to Child Controller like this

您可以像这样将值从Parent传递给Child Controller

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

现在您要将选择值传回给父视图控制器。为此,您可以在ChildController中创建一个Delegate

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

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

之后在ChildController中创建该委托的变量,就像这样

weak var delegate : ChildControllerDelegate?

and when in rowDidSelect method add following code

并在rowDidSelect方法中添加以下代码

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

现在,当您要从ParentController显示ChildController时,您必须将该委托对象设置为ParentController,就像这样

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

之后,只需在ParentController中实现委托方法

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

#2


0  

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

    将控制器转换为子视图控制器的相应类(我在下面使用ChildViewController,但希望你有一个更具描述性的名称);和

  • 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.

就个人而言,我不会像你在原始问题中那样硬编码儿童坐标。我将translatesAutoresizingMaskIntoConstraints设置为false,然后添加适当的前导/尾随/上/下限制,但这取决于你。在你的例子中看到硬编码坐标真是太痛苦了。

#3


0  

Try This.

尝试这个。

First Create Public Method For Add And Remove childVC.

首先创建添加和删除childVC的公共方法。

For Add childVC.

对于添加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.

对于删除childVC。

   public class func removeChildViewController(childVC:UIViewController){

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

Use Above Method.

使用上述方法。

1.ParentVC.swift

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

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)
}

#1


1  

You can pass value from Parent to Child Controller like this

您可以像这样将值从Parent传递给Child Controller

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

现在您要将选择值传回给父视图控制器。为此,您可以在ChildController中创建一个Delegate

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

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

之后在ChildController中创建该委托的变量,就像这样

weak var delegate : ChildControllerDelegate?

and when in rowDidSelect method add following code

并在rowDidSelect方法中添加以下代码

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

现在,当您要从ParentController显示ChildController时,您必须将该委托对象设置为ParentController,就像这样

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

之后,只需在ParentController中实现委托方法

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

#2


0  

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

    将控制器转换为子视图控制器的相应类(我在下面使用ChildViewController,但希望你有一个更具描述性的名称);和

  • 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.

就个人而言,我不会像你在原始问题中那样硬编码儿童坐标。我将translatesAutoresizingMaskIntoConstraints设置为false,然后添加适当的前导/尾随/上/下限制,但这取决于你。在你的例子中看到硬编码坐标真是太痛苦了。

#3


0  

Try This.

尝试这个。

First Create Public Method For Add And Remove childVC.

首先创建添加和删除childVC的公共方法。

For Add childVC.

对于添加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.

对于删除childVC。

   public class func removeChildViewController(childVC:UIViewController){

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

Use Above Method.

使用上述方法。

1.ParentVC.swift

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

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)
}