Swift中UITextView换行时设置新行文字为黑色的实现问题
解决UITextView回车后新行保持黑色的问题
错误原因分析
你之前的代码报错“Out of bounds”,是因为在shouldChangeTextIn方法中,当输入\n时,这个换行符还没被插入到textStorage里,此时你尝试给选中位置(还不存在字符的位置)设置长度为1的属性范围,自然会触发越界错误。
可行解决方案
方案1:手动插入带属性的换行符(推荐)
直接拦截系统的换行输入,手动创建带黑色属性的换行符插入文本,同时设置后续输入的默认属性为黑色:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { guard text == "\n" else { return true } // 创建带黑色文字属性的换行符 let blackNewLine = NSAttributedString(string: "\n", attributes: [.foregroundColor: UIColor.black]) // 将换行符插入到当前选中位置 textView.textStorage.insert(blackNewLine, at: range.location) // 把光标移到换行符之后,确保后续输入默认用黑色属性 textView.selectedRange = NSRange(location: range.location + 1, length: 0) // 设置后续输入的默认属性为黑色 textView.typingAttributes = [.foregroundColor: UIColor.black] return false // 阻止系统默认的换行插入行为 }
方案2:修正换行符属性+设置默认输入属性
允许系统先插入换行符,再在textViewDidChange中修正换行符的颜色,同时确保后续输入默认用黑色:
// 处理文本变化后的换行符颜色修正 func textViewDidChange(_ textView: UITextView) { let textLength = textView.textStorage.length guard textLength > 0 else { return } // 获取最后一个字符的范围 let lastCharRange = NSRange(location: textLength - 1, length: 1) let lastChar = textView.textStorage.string[textView.textStorage.string.index(textView.textStorage.string.startIndex, offsetBy: textLength - 1)] if lastChar == "\n" { // 检查换行符当前颜色,不是黑色则修改 let currentAttrs = textView.textStorage.attributes(at: lastCharRange.location, effectiveRange: nil) if let color = currentAttrs[.foregroundColor] as? UIColor, color != .black { textView.textStorage.addAttribute(.foregroundColor, value: UIColor.black, range: lastCharRange) } // 设置后续输入默认用黑色属性 textView.typingAttributes = [.foregroundColor: UIColor.black] } } // 提前设置换行后的默认输入属性 func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if text == "\n" { textView.typingAttributes = [.foregroundColor: UIColor.black] } return true }
关键说明
不需要给“空行”预先设置属性——因为空行本身没有字符,文本属性是依附于具体字符存在的。我们只需要给换行符\n设置黑色属性,同时通过typingAttributes指定光标位置的默认输入属性为黑色,就能保证后续输入的字符自动继承黑色,不受上一行浅灰色的影响。
内容的提问来源于stack exchange,提问作者Stefano Vet
相关产品推荐
相关产品推荐

