【问题标题】:Returning false in shouldChangeTextInRange method auto capitalize all letters在 shouldChangeTextInRange 方法中返回 false 自动将所有字母大写
【发布时间】:2019-10-17 05:39:34
【问题描述】:

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

我在 Xcode 11 中创建了一个小示例项目来解释这个问题。该项目针对 iOS 13。我正在运行 iOS 13.1.2 (17A860) 的 iPhone 8 上进行测试。该项目包含一个带有文本视图的简单视图控制器。 TextView 有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。但是当我输入时,第一个字符会被添加到大写字母中。第二个字符正确地以小写字母添加。从第三个字符开始,一切都大写。此外,在键入每个字符后,键盘切换按钮会自动被选中。附上截图。

其他一些重要的点。

  1. 仅当 autocapitalizationType 为 “sentences”,不适用于“words”、“none”等其他值。
  2. 我尝试在代码和情节提要中设置 autocapitalizationType, 结果相同。
  3. 如果我不实现shouldChangeTextInRange 方法,问题不是 转载。如果我从此方法返回 true,则问题不是 转载。由于我需要在这个方法中做一些处理,所以我 需要返回false。
  4. 尚未在 iOS 13 之前的设备上自行复制,尽管用户 在 iOS 12.4.1 上报告了此问题(目前未经验证)。

任何人都可以针对此问题提出修复/解决方法吗?

【问题讨论】:

    标签: ios uitextview ios13 capitalization iphone-softkeyboard


    【解决方案1】:

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

        textView.text = newString
    

    变成:

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

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

    【讨论】:

    • 这将导致自动更正建议停止工作。
    • 如果分配执行得太晚,在shouldChangeTextIn 中使用它会导致在不正确的位置添加新文本。但除非您进行繁重的处理,否则应该没问题。
    【解决方案2】:

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

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

    【讨论】:

    • 嗯,我也不得不使用相同的解决方法。这绝对看起来像一个 Apple 错误。
    • 赏金期结束。由于没有讨论其他解决方案并且我也必须遵循相同的解决方法,因此我将赏金给你。这绝对是 Apple 的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多