You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 21:55:30