我应该如何访问存储在持有容器视图的视图控制器中的IBOutlet? (斯威夫特4)

时间:2017-06-24 17:25:48

标签: ios swift xcode

在我的应用程序中,我希望在主视图控制器中存储多个容器视图。从那里我希望能够从主视图控制器和容器视图修改容器视图的约束。

我制作了一个简单的Xcode项目并制作了一个示例GIF,展示了我希望能够做到的事情。

Simulator GIF

Storyboard

"重置"按钮存储在我的主视图控制器的容器视图中。容器视图使用约束垂直和水平居中。 " Up"," Right"," Down"和" Left"按钮修改容器视图的现有约束。我希望能够使用"重置"修改容器视图的约束。容器视图内的按钮。

每次我尝试从容器视图中访问/修改存储在主视图控制器中的约束IBOutlets时,它会崩溃说"致命错误:意外地发现nil"。

实现此功能的最佳方法是什么?我全神贯注于你的建议。

提前致谢。

ViewController.swift(主视图控制器)

class ViewController: UIViewController {
    @IBOutlet weak var ContainerViewVerticalConstraint: NSLayoutConstraint!
    @IBOutlet weak var ContainerViewHorizontalConstraint: NSLayoutConstraint!

    @IBAction func upButtonPressed(_ sender: Any) {
        ContainerViewVerticalConstraint.constant = -100
    }

    @IBAction func rightButtonPressed(_ sender: Any) {
        ContainerViewHorizontalConstraint.constant = 50
    }

    @IBAction func downButtonPressed(_ sender: Any) {
        ContainerViewVerticalConstraint.constant = 100
    }

    @IBAction func leftButtonPressed(_ sender: Any) {
        ContainerViewHorizontalConstraint.constant = -50
    }
}

ContainerViewController.swift(容器视图)

class ContainerViewController: UIViewController {
    @IBAction func resetButtonPressed(_ sender: Any) {
        // Modify the constraints of the container view when this button is pressed
    }
}

2 个答案:

答案 0 :(得分:3)

容器视图嵌入了嵌入segue。您可以执行以下操作:

  1. 文档大纲中找到embed segue,并为其指定"embedResetView"等标识符。
  2. prepareForSegue中,如果segue.identifier"embedResetView",则将两个约束传递给目标(重置)视图中的属性。约束是对象,因此它们通过引用传递。

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "embedResetView" {
            if let dvc = segue.destination as? ContainerViewController {
                dvc.horizontalConstraint = ContainerViewHorizontalConstraint
                dvc.verticalConstraint = ContainerViewVerticalConstraint
            }
        }
    }
    
  3. 按下reset按钮后,修改这些约束中的constant属性。

    class ContainerViewController: UIViewController {
        weak var horizontalConstraint: NSLayoutConstraint?
        weak var verticalConstraint: NSLayoutConstraint?
    
        @IBAction func resetButtonPressed(_ sender: Any) {
            horizontalConstraint?.constant = 0
            verticalConstraint?.constant = 0
        }
    }
    

答案 1 :(得分:2)

您可以使用委托模式在视图控制器之间传递事件或数据。

首先,您应该在ContainerViewController中创建一个协议:

protocol ContainerViewControllerDelegate: class {
    func containerControllerDidRequestViewReset()
}

之后,将一个委托属性添加到ContainerViewController:

weak var delegate: ContainerViewControllerDelegate?

在您的重置按钮功能中,调用协议方法:

@IBAction func resetButtonPressed(_ sender: Any) {
    // Modify the constraints of the container view when this button is pressed
    delegate?.containerControllerDidRequestViewReset()
}

然后,导航到您的Storyboard文件并从ViewController向ContainerViewController添加标识符,例如" ToContainerViewSegueID"。 在您的主ViewController类中实现以下方法:

func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ToContainerViewSegueID" {
        if let containerVC = segue.destination as? ContainerViewController {
            containerVC.delegate = self
        }
    }
}

之后,您应该将ContainerViewControllerDelegate实现到主ViewController类中。例如,您可以使用相同的文件中的扩展名来执行此操作:

class ViewController: UIViewController {
    //your code goes here
}

extension ViewController: ContainerViewControllerDelegate {
    func containerControllerDidRequestViewReset() {
        //here is a good place to reset your constraints values
        ContainerViewVerticalConstraint.constant = 0
        ContainerViewHorizontalConstraint.constant = 0
    }
}