shouldChangeTextInRange方法返回false会自动将所有字母大写

14

我在最新的iOS版本中使用UITextView时遇到了奇怪的问题。据我目前的理解,这仅发生在iOS 13中。尽管有一个用户报告iOS 12.4.1上存在此问题,但我无法在任何早于iOS 13的设备上重现此问题。

我在Xcode 11中创建了一个小示例项目以解释此问题。该项目针对iOS 13进行了定位。我在运行iOS 13.1.2(17A860)的iPhone 8上进行测试。该项目包含一个简单的视图控制器和一个文本视图。文本视图的autoCapitalizationType为“句子”。然后我实现了代理方法shouldChangeTextInRange。请参见下面的代码

class ViewController: UIViewController {  
    @IBOutlet weak var textView: UITextView!  
    override func viewDidLoad() {  
        super.viewDidLoad()  
        self.textView.delegate = self  
        self.textView.autocapitalizationType = .sentences  
    }  
}  
  
extension ViewController: UITextViewDelegate {  
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange,
      replacementText text: String) -> Bool {  
        //I wanted to do some other modifications here, but for now just
        //setting the user typed text manually and returning false  
        if let oldString = textView.text {  
            let newString = oldString.replacingCharacters(in: Range(range, in: oldString)!,  
                                                          with: text)  
            textView.text = newString  
        }  
        return false  
    }  
}  

这是整个代码,除了故事板和其他项目文件。如上所述,我只是手动将用户输入的确切文本设置到TextView中,然后返回false。但是当我开始输入时,第一个字符按正确的方式大写。第二个字符以小写形式正确添加。从第三个字符开始,所有内容都以大写字母显示。此外,每次键入字符后都会自动选择键盘大小写转换按钮。已附屏幕截图。

enter image description here

一些其他重要要点。

  1. 仅在自动大写类型为“句子”时出现此问题,而在其他值(如“单词”,“无”)中不会出现。
  2. 我尝试在代码和故事板中设置autocapitalizationType,结果相同。
  3. 如果我不实现shouldChangeTextInRange方法,则不会出现此问题。如果我从该方法返回true,则不会出现此问题。因为我需要在此方法中执行一些处理,所以我需要返回false。
  4. 尚未在iOS 13之前的设备上复制,尽管用户在iOS 12.4.1上报告了此问题(现在还没有验证)。

有人能提供此问题的修复/解决方法吗?

2个回答

11

尝试在主循环中安排此赋值语句:

    textView.text = newString

成为:

    DispatchQueue.main.async {
        textView.text = newString
    }

这对我成功解决了一个类似的问题,即句子的前两个字母被大写。我的猜测是UITextView的text属性的didSet监听器背后的逻辑发生了变化,以一种立即同步触发委托的方式。在主队列上异步调度赋值可以强制/确保在第二次触发之前返回委托。


1
这将导致自动更正建议停止工作。 - user3199693
shouldChangeTextIn 中使用这个会导致新文本在执行赋值操作太晚时添加到错误的位置。但是,除非您正在进行大量处理,否则应该没问题。 - förschter

9
到目前为止,我找到的最佳解决方法是在textViewDidChange中进行处理。
这个错误在这里也有讨论:Apple 开发者论坛

嗯,我也不得不使用同样的解决方法。这明显是一个苹果的 bug。 - Krishnabhadra
赏金期已结束。由于没有讨论其他解决方案,而我也不得不遵循同样的解决方法,所以我将赏金给了你。这绝对是一个苹果的 bug。 - Krishnabhadra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接