UITextView大小写显示切换与编辑时保留原字符串大小写的问题
解决UITextView显示变形字符串同时保留原字符串的问题
你的核心痛点在于:既要切换UITextView的显示大小写,又要准确维护用户输入的原始大小写字符串,而之前用shouldChangeTextIn的复杂逻辑导致了预测词输入等场景的异常。这里提供一个更简洁可靠的方案,核心思路是完全分离真实数据源和显示文本,统一处理所有编辑操作。
核心实现思路
- 用单独的变量保存用户输入的原始大小写字符串(作为真实数据源)。
- UITextView的显示文本仅根据开关状态,显示原始字符串的原格式或全大写格式。
- 在
shouldChangeTextIn中直接利用系统传入的编辑参数更新原始数据源,再同步更新显示文本,同时手动维护光标位置,避免系统默认处理带来的冲突。
完整代码示例
import UIKit class ViewController: UIViewController { lazy var textView: UITextView = { let txtv = UITextView(frame: CGRect(x: 0, y: 40, width: view.frame.width, height: 200)) txtv.autoresizingMask = [.flexibleWidth, .flexibleHeight] txtv.delegate = self txtv.font = UIFont.systemFont(ofSize: 22) return txtv }() lazy var toggleButton: UIButton = { let btn = UIButton(frame: CGRect(x: 20, y: 250, width: view.frame.width - 40, height: 50)) btn.autoresizingMask = [.flexibleWidth, .flexibleHeight] btn.setTitleColor(.blue, for: .normal) btn.setTitle("TOGGLE CAPITALIZATION", for: .normal) btn.addTarget(self, action: #selector(toggleCapitalizationState), for: .touchUpInside) return btn }() // 真实数据源:保存用户输入的原始大小写文本 var originalText = "This is a test to see how we are doing" // 显示状态开关:是否以全大写显示 var shouldShowUppercase = true override func viewDidLoad() { super.viewDidLoad() view.addSubview(textView) view.addSubview(toggleButton) updateDisplayText() } /// 更新UITextView的显示文本 private func updateDisplayText() { textView.text = shouldShowUppercase ? originalText.uppercased() : originalText // 保持光标位置不变,避免切换显示状态时光标跳走 let currentCursorRange = textView.selectedRange textView.selectedRange = currentCursorRange } @objc private func toggleCapitalizationState() { shouldShowUppercase.toggle() updateDisplayText() } } extension ViewController: UITextViewDelegate { func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { // 1. 更新原始数据源:直接利用系统传入的range和text修改原始文本 let originalNSString = originalText as NSString originalText = originalNSString.replacingCharacters(in: range, with: text) // 2. 同步更新显示文本 updateDisplayText() // 3. 手动维护光标位置:原range起始位置 + 替换文本的长度 let newCursorLocation = range.location + text.count textView.selectedRange = NSRange(location: newCursorLocation, length: 0) // 禁止系统默认处理,避免和我们的手动更新冲突 return false } }
方案优势
- 无hack逻辑:移除了原代码中针对预测输入的临时标记,所有编辑场景(普通输入、选中文本替换、预测词输入、删除操作)都能统一处理。
- 数据源与显示解耦:原始文本和显示文本完全分离,不会出现大小写转换导致的不可逆问题。
- 光标位置稳定:手动计算光标位置,确保编辑后光标始终处于预期位置,提升用户体验。
内容的提问来源于stack exchange,提问作者agibson007
相关产品推荐
相关产品推荐

