如何使用UIKit在UITextView/NSTextView中实现文本缩进与取消缩进功能
UITextView/NSTextView 缩进/取消缩进实现方案
核心思路
选择**插入制表符\t**作为缩进标记,而非富文本段落缩进属性,无需额外重写复制逻辑,系统原生剪贴板会自动携带文本内的\t字符,粘贴到任意编辑器都能保留缩进格式,兼容性更强。
完整代码实现
1. 先给UITextView加扩展封装缩进逻辑
extension UITextView { /// 缩进选中文本(无选中文本则在当前光标位置插入缩进) func indent() { guard let selectedRange = selectedTextRange else { return } // 选中内容为空,直接插入\t if selectedRange.start == selectedRange.end { replace(selectedRange, withText: "\t") return } // 选中多行内容,逐行添加缩进 guard let text = text(in: selectedRange) else { return } let lines = text.components(separatedBy: .newlines) let indentedLines = lines.map { "\t" + $0 } let indentedText = indentedLines.joined(separator: "\n") replace(selectedRange, withText: indentedText) // 调整选中范围为缩进后的内容 if let newStart = position(from: selectedRange.start, offset: 0), let newEnd = position(from: newStart, offset: indentedText.count) { selectedTextRange = textRange(from: newStart, to: newEnd) } } /// 取消选中文本的缩进 func outdent() { guard let selectedRange = selectedTextRange else { return } guard let text = text(in: selectedRange) else { return } let lines = text.components(separatedBy: .newlines) let outdentedLines = lines.map { line -> String in guard line.first == "\t" else { return line } return String(line.dropFirst()) } let outdentedText = outdentedLines.joined(separator: "\n") replace(selectedRange, withText: outdentedText) // 调整选中范围为取消缩进后的内容 if let newStart = position(from: selectedRange.start, offset: 0), let newEnd = position(from: newStart, offset: outdentedText.count) { selectedTextRange = textRange(from: newStart, to: newEnd) } } }
2. 在你的ViewController中调用
你可以绑定两个按钮的点击事件触发缩进/取消缩进:
class ViewController: UIViewController { @IBOutlet weak var textView: UITextView! override func viewDidLoad() { super.viewDidLoad() textView.delegate = self } // 绑定缩进按钮的点击事件 @IBAction func indentButtonTapped(_ sender: UIButton) { textView.indent() } // 绑定取消缩进按钮的点击事件 @IBAction func outdentButtonTapped(_ sender: UIButton) { textView.outdent() } } extension ViewController: UITextViewDelegate { // 你原有其他delegate逻辑可保留在这里 }
NSTextView 适配说明
逻辑和上述实现完全一致,只需要替换API名称即可:
- 将
UITextView替换为NSTextView selectedTextRange替换为selectedRange- 文本替换使用
replaceCharacters(in:with:)方法即可
效果验证
缩进后的文本直接执行复制操作,粘贴到任意纯文本/富文本编辑器都会自动携带缩进格式,无需额外处理剪贴板逻辑。
内容的提问来源于stack exchange,提问作者Nighthawk
相关产品推荐
相关产品推荐

