Swift更新Main.storyboard约束时无法访问textView底部约束问题
问题根本原因
你要找的底部约束本身就不存在于self.textView.constraints数组中:
- iOS布局系统中,视图的
constraints数组仅存储两类约束:一类是作用于该视图自身的内部约束(比如固定宽高约束),另一类是该视图和它的直接子视图之间的约束。 - 你在Storyboard中设置的textView底部约束,属于textView和它的父视图之间的跨视图约束,这类约束默认会被添加到两个视图的最近公共父视图上,也就是textView的父视图的
constraints数组里,所以你遍历textView的约束数组自然匹配不到目标。 - 补充说明:正常加载完成的textView的
constraints不会为nil,只会是空数组,如果你确认拿到的是nil,需要先检查textView的IBOutlet关联是否正常,有没有提前在视图未加载完成的时候访问了textView属性。
代码修复方案
方案1:直接关联约束IBOutlet(推荐)
不需要遍历查找,直接在Storyboard中把标识符为bottomTextViewConstraint的约束拖线关联到当前控制器的属性,拿到引用后直接修改即可,代码示例:
// 控制器中声明约束属性 @IBOutlet weak var bottomTextViewConstraint: NSLayoutConstraint! @objc func keyboardWillShow(notification: NSNotification) { guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return } bottomTextViewConstraint.constant = keyboardSize.height // 修改常量后触发父视图布局生效,不要调用textView.updateConstraints() view.layoutIfNeeded() }
方案2:遍历父视图约束查找
如果你不想拖线关联,修改遍历逻辑,从textView的父视图的约束数组中匹配标识符即可:
@objc func keyboardWillShow(notification: NSNotification) { guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue, let superview = textView.superview else { return } for constraint in superview.constraints { if constraint.identifier == "bottomTextViewConstraint" { constraint.constant = keyboardSize.height break } } view.layoutIfNeeded() }
另外注意你原代码中的错误:修改约束constant后调用textView.updateConstraints()不会触发布局生效,需要调用当前控制器根视图的layoutIfNeeded()方法才能让约束变更生效。
内容的提问来源于stack exchange,提问作者user16717743
相关产品推荐
相关产品推荐

