UITextView占位符引发第二个字母自动大写及加载不显示问题
UITextView占位符功能异常修复方案
问题描述
实现了类似Twitter发帖界面的UITextView占位符功能,控件位于CollectionReusableView中,出现两个异常:
- 输入时第二个字母自动大写
viewDidLoad时占位符不显示
原代码
lazy var textView: UITextView = { let view = UITextView() view.translatesAutoresizingMaskIntoConstraints = false view.delegate = self view.text = "What's happening?" view.textColor = .lightGray view.textContainerInset = .zero view.textContainer.lineFragmentPadding = 0.0 view.font = UIFont.systemFont(ofSize: 20) return view }() func textViewDidBeginEditing(_ textView: UITextView) { if textView.textColor == UIColor.lightGray { textView.text = nil textView.textColor = .label } } func textViewDidEndEditing(_ textView: UITextView) { if textView.text.isEmpty { textView.text = "What's happening?" textView.textColor = UIColor.lightGray } } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { let currentText: String = textView.text let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text) if updatedText.isEmpty { textView.text = "What's happening?" textView.textColor = .lightGray textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument) } else if textView.textColor == UIColor.lightGray && !text.isEmpty { textView.textColor = .label textView.text = text } else { return true } return false } func textViewDidChangeSelection(_ textView: UITextView) { if textView.textColor == UIColor.lightGray { textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument) } }
异常修复方案
1. 输入时第二个字母自动大写问题
问题出在shouldChangeTextIn方法的首次输入逻辑:直接用textView.text = text替换文本,跳过了系统默认的文本输入流程,导致自动大写的状态异常。
修改后的shouldChangeTextIn方法:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { let currentText: String = textView.text let updatedText = (currentText as NSString).replacingCharacters(in: range, with: text) if updatedText.isEmpty { textView.text = "What's happening?" textView.textColor = .lightGray textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument) return false } else if textView.textColor == UIColor.lightGray && !text.isEmpty { // 清空占位符,让系统处理首次输入流程 textView.text = nil textView.textColor = .label return true } else { return true } }
2. viewDidLoad时占位符不显示问题
CollectionReusableView的viewDidLoad不是布局完成的时机,UITextView的frame可能未正确初始化;同时复用控件时也需要重置占位符状态。
在你的CollectionReusableView类中添加以下代码:
override func layoutSubviews() { super.layoutSubviews() // 布局完成后确保占位符状态正确 if textView.text.isEmpty || textView.textColor == .lightGray { textView.text = "What's happening?" textView.textColor = .lightGray } } override func prepareForReuse() { super.prepareForReuse() // 复用前重置占位符 textView.text = "What's happening?" textView.textColor = .lightGray textView.selectedTextRange = textView.textRange(from: textView.beginningOfDocument, to: textView.beginningOfDocument) }
内容的提问来源于stack exchange,提问作者David Henry
相关产品推荐
相关产品推荐

