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

View Controller loses connection to constraints in IBOutlets when switching tabs in UITabView

好的,下面是我的代码的相关部分:

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

我正在构建 question/answer 类型的应用程序,由于设计原因,两个子视图的大小不同。我将其设置为根据当前状态在两个子视图之间切换(当用户点击前进时切换回新问题),并且工作正常...

...直到我转到 UITabView 上包含所有内容的不同选项卡(例如,更改设置然后恢复测试)

选项卡更改的那一刻,就好像 NSLayoutConstraint 网点不再存在一样。更改它们的命令仍在处理中(我已在控制台中验证了这一点),但它们什么也没做。

关于如何解决这个问题有什么建议吗?

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

如果你有这个:

@IBOutlet weak var tableViewTopAlternateConstraint: NSLayoutConstraint!

通过 Storyboard 连接到一个约束,你这样做:

tableViewTopAlternateConstraint.isActive = false

你只是移除了那个约束。

此外,如果您在 Storyboard 中有两个不同的 Top 约束,您应该会收到错误指示器,因为它们无法满足。

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

因此,Storyboard 中的两个约束:

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

您的代码变为:

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

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