返回页面后UITextView无法滚动问题求助(附代码)
UITextView 返回后无法滚动的问题修复
问题现象
首次输入大量文本时,UITextView可正常滚动;跳转到第二个视图控制器后返回,UITextView失去滚动能力。移除placeholder label后问题消失,添加后复现。
问题原因
placeholderLabel被添加为UITextView的子视图,且设置了固定高度约束(60),同时开启translatesAutoresizingMaskIntoConstraints = false。返回页面重新填充文本时,该约束会强制限制UITextView的内容视图高度,导致滚动逻辑失效。
修复方案
- 移除placeholderLabel的固定高度约束,改用与UITextView字体行高匹配的动态约束,或直接不设置高度约束让label自适应内容;
- 确保placeholderLabel的隐藏状态与文本内容同步,避免干扰UITextView布局计算;
- 返回页面时手动触发UITextView布局更新,确保内容尺寸正确计算。
修改后的关键代码
1. 调整placeholderLabel约束(修改buildConstraints方法)
func buildConstraints() { // 其他控件约束保持不变 nameLabel.translatesAutoresizingMaskIntoConstraints = false nameLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true nameLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true nameLabel.heightAnchor.constraint(equalToConstant: 60).isActive = true textView.translatesAutoresizingMaskIntoConstraints = false textView.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 8).isActive = true textView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 8).isActive = true textView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -8).isActive = true textView.bottomAnchor.constraint(equalTo: saveButton.topAnchor, constant: -8).isActive = true // 修改placeholderLabel约束:移除固定高度,改用字体行高匹配的约束 placeholderLabel.translatesAutoresizingMaskIntoConstraints = false placeholderLabel.leadingAnchor.constraint(equalTo: textView.leadingAnchor, constant: 10).isActive = true placeholderLabel.trailingAnchor.constraint(equalTo: textView.trailingAnchor).isActive = true placeholderLabel.topAnchor.constraint(equalTo: textView.topAnchor).isActive = true // 替换固定高度为与textView字体行高匹配的约束 placeholderLabel.heightAnchor.constraint(equalToConstant: textView.font?.lineHeight ?? 20).isActive = true saveButton.translatesAutoresizingMaskIntoConstraints = false saveButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true saveButton.heightAnchor.constraint(equalToConstant: 50).isActive = true saveButton.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.8).isActive = true saveButton.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor, constant: -10).isActive = true }
2. 移除placeholderLabel的frame设置(修改setUpPlaceHolderLabel方法)
func setUpPlaceHolderLabel() { placeholderLabel.backgroundColor = UIColor.clear placeholderLabel.text = NSLocalizedString("enter text", comment: "") placeholderLabel.textColor = UIColor.lightGray placeholderLabel.font = UIFont(name: "Arial", size: 20) // 移除frame设置,改用AutoLayout约束控制位置 // placeholderLabel.frame.origin = CGPoint(x: 5, y: (textView.font?.pointSize)! / 2) }
3. 页面返回时强制更新布局(修改viewWillAppear方法)
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) textView.isScrollEnabled = true textView.isUserInteractionEnabled = true buildPriorText() // 强制更新布局,确保内容尺寸正确计算 textView.layoutIfNeeded() // 同步placeholderLabel的隐藏状态 placeholderLabel.isHidden = !textView.text.isEmpty }
补充说明
- UITextView的子视图若设置不合理约束,会干扰其内部内容布局计算,尤其是滚动相关逻辑;
- 使用AutoLayout时,避免同时设置frame和约束,二者选其一即可;
- 返回页面重新填充文本后,手动触发
layoutIfNeeded()可确保UITextView重新计算内容尺寸,恢复滚动能力。
内容的提问来源于stack exchange,提问作者Edward Curley
相关产品推荐
相关产品推荐

