Swift开发iOS14设备下UITextView高度修改后UI未更新问题求解
iOS14 UITextView修改高度后UI未同步更新问题修复
问题根因
- iOS14对UITextView的布局刷新逻辑做了系统级调整,当控件同时存在自动布局约束和手动frame修改操作时,系统会优先以约束计算结果为准,直接覆盖手动修改的frame值。iOS13及更低版本对混合布局的容错更高,会优先取最后设置的frame值,因此问题仅出现在iOS14设备上。
- 你当前代码同时混用「手动修改UITextView frame」和「触发父视图约束更新」两种布局逻辑,触发了iOS14的布局优先级判断规则,导致修改的frame被自动重置。
修复方案
方案1:全量使用自动布局实现(推荐)
不要手动修改frame,通过修改高度约束的constant值实现自适应,适配所有系统版本:
// 先通过xib/纯代码给inputTextView添加高度约束,关联为成员属性 @IBOutlet weak var textViewHeightConstraint: NSLayoutConstraint! func textViewDidChange(_ textView: UITextView) { let size = textView.sizeThatFits(CGSize(width: textView.frame.width, height: CGFloat(MAXFLOAT))) textViewHeightConstraint.constant = size.height // 触发父视图布局刷新,可加动画让过渡更自然 UIView.animate(withDuration: 0.2) { self.messageInputContainerView.layoutIfNeeded() } }
方案2:坚持使用frame布局的适配方案
如果业务逻辑需要保留frame修改方式,禁止触发父视图约束更新,直接强制刷新布局即可:
func textViewDidChange(_ textView: UITextView) { let size = textView.sizeThatFits(CGSize(width: textView.frame.width, height: CGFloat(MAXFLOAT))) var frame = textView.frame frame.size.height = size.height textView.frame = frame // 强制刷新当前控件和父视图布局,不要调用setNeedsUpdateConstraints textView.layoutIfNeeded() self.messageInputContainerView.layoutIfNeeded() }
注意事项
- 计算高度前请确保UITextView的
isScrollEnabled属性为false,否则sizeThatFits会返回固定高度而非内容实际高度 - 不要混用frame修改和自动布局约束更新操作,两种布局方式二选一即可,避免系统布局优先级判断异常
内容的提问来源于stack exchange,提问作者minimomo
相关产品推荐
相关产品推荐

