在UITabView中切换选项卡时,View Controller失去与IBOutlets中的约束的连接

问题描述

好的,所以这是我的代码的相关部分:

class MyViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
    @IBOutlet weak var questionView: QuestionView!
    @IBOutlet weak var answerView: AnswerView!
    
    @IBOutlet weak var tableView: UITableView!
    
    @IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint! // Active at start,attaches tableView.topAnchor to questionView.bottomAnchor
    @IBOutlet weak var tableViewTopAlternateConstraint: NSLayoutConstraint! // Inactive at start,attaches tableView.topAnchor to answerView.bottomAnchor
    
    func submitAnswer() {
        tableViewTopConstraint.isActive = false
        tableViewTopAlternateConstraint = true
    }
    
    func newQuestion() {
        tableViewTopConstraint.isActive = true
        tableViewTopAlternateConstraint = false
    }
}

我正在构建应用程序的问题/答案类型,由于设计原因,两个子视图的大小不同。我对其进行了设置,使其可以根据当前状态在两个子视图之间切换(当用户点击以前进时切换回一个新问题),并且效果很好...

...直到我转到UITabView上包含所有内容的其他标签(例如,更改设置然后恢复测试)

标签更改的那一刻,就像NSLayoutConstraint出口不再存在。更改它们的命令仍在处理(我已经在控制台中对此进行了验证),但是它们什么也不做。

  • 我尝试声明门店为强(行为上没有差异)
  • 我已经移除了网点,并使用代码对其进行了管理(这是第一次,但是后来它拉长了较短的QuestionView的高度以匹配tableView的新最高位置而不是将tableView移到QuestionView底部
  • 我尝试实现UITabViewController,以便每当我切换回该选项卡时,都可以调用tabBar(_:didSelect:)并将视图控制器替换为全新的MyViewController()实例(它是第一次加载,但是当我尝试切换标签时,在访问任何nil时都会找到IBOutlet ...即使我没有点击测试视图的标签,替换现有的视图控制器时被item.tag过滤)

关于如何进一步解决此问题的任何建议?

解决方法

首先,不要将@IBOutlet属性设置为weak。我知道这是默认设置,但这是不正确的。

如果您有这样的话:

@IBOutlet weak var tableViewTopAlternateConstraint: NSLayoutConstraint!

通过Storyboard连接到约束,您可以执行以下操作:

tableViewTopAlternateConstraint.isActive = false

您只是 删除了 该约束而已。

此外,如果在Storyboard中有两个不同的Top约束,则应该获得一个Error指示符,因为它们无法满足。

最好更改优先级,或使用单个约束并更改.constant值。

因此,情节提要中有两个约束:

  • 将“默认”约束设置为Priority: High (750)
  • 将“替代”约束设置为PriorityL Low (250)

,您的代码将变为:

func submitAnswer() {
    tableViewTopConstraint.priority = .defaultLow
    tableViewTopAlternateConstraint.priority = .defaultHigh
}

func newQuestion() {
    tableViewTopAlternateConstraint.priority = .defaultLow
    tableViewTopConstraint.priority = .defaultHigh
}