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

Posted

技术标签:

【中文标题】如何在父视图控制器和子视图控制器之间传输数据【英文标题】:How to transfer data between Parent and Child View Controllers 【发布时间】:2017-09-13 11:21:33 【问题描述】:

我已尝试查看与此类似的问题的答案,但我并不是特别有经验,并且在关注它们时遇到了麻烦,因此非常感谢任何帮助!我的情况如下:当我在Parent 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)

然后我想要将一个数组从 Parent 传输到 Child,它将用作 TableView 的数据?

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

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

我非常感谢任何建议,即使它是指向有用的东西的链接!

【问题讨论】:

您可以像在任意两个视图控制器之间传递数据一样传递数组。在addChildViewController(controller!) 行之后,您可以添加controller.array = self.array。并返回,您可以使用委托方法。 您可以将parentsViewVontrollerparentsViewVontroller's 实例中的属性设置为childViewController 并将值传递给此变量,或者您可以创建childViewController 的委托并可以接收回事件或者您可以使用积木。 【参考方案1】:

你可以像这样将值从父控制器传递给子控制器

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)

现在您想将您的选择值传回父视图控制器。为此,您需要在 ChildController 中创建一个委托,例如

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

然后像这样在 ChildController 中为该委托创建一个变量

weak var delegate : ChildControllerDelegate?

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

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

现在,当您要从 ParentController 显示 ChildController 时,您必须像这样将 delegate 对象设置为 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)

然后像这样在 ParentController 中实现委托方法

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

【讨论】:

【参考方案2】:

试试这个。

首先为添加和删除 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)
    

对于删除 childVC。

   public class func removeChildViewController(childVC:UIViewController)

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

使用上述方法。

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)

【讨论】:

【参考方案3】:

你可以:

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

将当前视图控制器(父级)中的数组(我猜你可能叫people,但使用这两个视图控制器中的任何数组名)传递给这个新的子视图控制器.

因此:

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

就个人而言,我不会像您在原始问题中那样对子坐标进行硬编码。我会将translatesAutoresizingMaskIntoConstraints 设置为false,然后添加适当的前导/尾随/顶部/底部约束,但这取决于您。在您的示例中看到硬编码的坐标太痛苦了。

【讨论】:

感谢您的建议!打算先让事情正常工作,然后再进行自动调整(对此很新,所以我想这可能不是正确的做事方式!)

以上是关于如何在父视图控制器和子视图控制器之间传输数据的主要内容,如果未能解决你的问题,请参考以下文章

Xcode(Swift):我无法在视图控制器之间传输数据

在视图控制器之间传输浮点值 [重复]

自动布局和 UIScrollview 和子视图控制器问题

无法在表视图和另一个视图控制器之间传递数据

IOS Swift:如何在两个控制器之间传输数据

在父视图控制器上注册一个 Segue 以在子视图控制器上使用