在 shouldChangeTextInRange 方法中返回 false 自动大写所有字母

Returning false in shouldChangeTextInRange method auto capitalize all letters

我发现最新 iOS 版本的 UITextView 存在一个奇怪的问题。根据我目前的理解,它仅发生在 iOS 13 中。我的一位用户在 iOS 12.4.1 上报告了这一点,但我无法在 iOS 13 之前的任何版本中重现这一点设备。

我在 Xcode11 中创建了一个小示例项目来解释这个问题。该项目的目标是 iOS 13。我正在 iPhone 8 运行 iOS 13.1.2 (17A860) 上进行测试。该项目包含一个带有文本视图的简单视图控制器。 TextView 有 autoCapitalizationType 作为 "Sentences"。然后我实现了委托方法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  
    }  
}  

这是完整的代码,除了故事板和其他项目文件。正如您在上面看到的,我只是将用户输入到文本视图中的完全相同的文本手动设置为 return false。但是当我打字时,第一个字符会按原样添加到大写字母中。第二个字符以小写字母正确添加。从第三个字符开始,一切都在大写。此外,在键入每个字符后,键盘切换按钮会自动被选中。附上截图。

其他一些要点。

  1. 仅当 autocapitalizationType 为 "sentences",不适用于 "words"、"none".
  2. 等其他值
  3. 我尝试在代码和故事板中设置 autocapitalizationType, 结果相同。
  4. 如果我不实施 shouldChangeTextInRange 方法,问题就不是 转载。如果我从这个方法 return true ,问题就不是 转载。由于我需要在这个方法中做一些处理,我 需要 return false.
  5. 尚未在 iOS 13 之前的设备上自行复制,尽管用户 在 iOS 12.4.1 上报告了这一点(目前尚未验证)。

任何人都可以为这个问题提出 fix/workaround 吗?

到目前为止,我发现的最佳解决方法是改为在 textViewDidChange 中进行处理。

这里也讨论了这个错误:Apple developer forum

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

    textView.text = newString

变为:

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

这成功地解决了我遇到的类似问题,即句子的前两个字母被大写。我最好的猜测是 UITextView 的文本 属性 的 didSet 侦听器背后的逻辑以立即同步触发委托的方式发生了变化。在第二次被解雇之前,在主队列 forces/guarantees 委托 returns 上异步安排分配。