在 UITabView 中切换选项卡时,视图控制器与 IBOutlets 中的约束失去连接

Posted

技术标签:

【中文标题】在 UITabView 中切换选项卡时,视图控制器与 IBOutlets 中的约束失去连接【英文标题】:View Controller loses connection to constraints in IBOutlets when switching tabs in UITabView 【发布时间】:2020-11-04 19:36:46 【问题描述】:

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

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 的新顶部位置,而不是移动@ 987654326@ 到 QuestionView 的底部,如预期的那样) 我已经尝试实现UITabViewController,这样我就可以调用tabBar(_:didSelect:),并在我切换回该选项卡时用MyViewController() 的全新实例替换视图控制器(它第一次加载,但是当我尝试切换选项卡时,它会在访问任何IBOutlets 时找到nil...即使我没有点击测试视图的选项卡并在替换现有视图时由item.tag 过滤控制器)

关于如何解决这个问题的任何建议?

【问题讨论】:

"这是我的代码的相关部分" ...您可能认为这是相关部分,但事实并非如此。您还没有在其他任何地方展示您可能正在做的任何事情(例如在viewDidAppear()?)。使用标签栏控制器和两个视图控制器开始一个新项目。在第一个中,添加一个视图和一个按钮,将视图的顶部约束连接到@IBOutlets,只需要测试它的最少代码。 回到选项卡后只需更新约束 顺便说一句...@IBOutlet weak var tableViewTopAlternateConstraint: NSLayoutConstraint! // Inactive at start ---它是如何“在开始时不活动”的? @DonMag 如果您在 Interface Builder 中选择了非活动约束,则未选中“已安装”复选框。因此,两个约束中的第一个是唯一有效的约束(并且 IB 不会记录它们之间的冲突,即使 tableView 否则会有两个冲突的值)。 @Kaji - 取消选中“已安装”意味着 “不要在运行时安装此约束”...这显然不是您想要的。 【参考方案1】:

首先,不要将@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

【讨论】:

感谢您的见解!我正在处理的程序仍然存在问题,但是我从一个新项目中的新构建开始,并内置了所有讨论过的组件,并且概念验证工作正常。基于此,我对此进行了复选标记,并可能会看到将我的代码移植到概念验证应用程序设置中,以查看我是否可以确定潜在的问题。

以上是关于在 UITabView 中切换选项卡时,视图控制器与 IBOutlets 中的约束失去连接的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式切换选项卡时清除根视图控制器的变量

切换选项卡时未调用 NSFetchedResultsControllerDelegate 方法

IllegalArgumentException:快速切换 ActionBar 选项卡时没有找到片段 id 的视图

当通过手势识别器滑动切换到仅点击选项卡时,在 tabbarcontroller 中切换选项卡会给出不同的结果

切换到片段选项卡主机中的选项卡时查看寻呼机丢失其内容

集合视图/选项卡栏控制器崩溃