Возвращение false в методе shouldChangeTextInRange автоматически делает все буквы заглавными

Я наблюдаю странную проблему с UITextView в последних версиях iOS. Насколько я понимаю, это происходит только в iOS 13. Один из моих пользователей сообщил об этом в iOS 12.4.1, хотя я не могу воспроизвести это на каких-либо устройствах до iOS 13.

Я создал небольшой образец проекта в Xcode 11, чтобы объяснить проблему. Проект нацелен на iOS 13. Я тестирую iPhone 8 под управлением iOS 13.1.2 (17A860). Проект содержит простой контроллер представления с текстовым представлением. TextView имеет autoCapitalizationType как «предложения». Затем я реализовал метод делегата shouldChangeTextInRange method. См. Код ниже

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  
    }  
}  

Это весь код, кроме раскадровки и других файлов проекта. Как вы можете видеть выше, я просто устанавливаю тот же текст, который пользователь вводит в текстовое представление вручную, а затем возвращаю false. Но когда я печатаю, первый символ добавляется заглавными буквами, как и должно. Второй символ правильно добавляется строчной буквой. Начиная с третьего символа, все пишется заглавными буквами. Более того, кнопка переключения клавиатуры автоматически выбирается после ввода каждого символа. Скриншот прилагается.

введите описание изображения здесь

Еще несколько важных моментов.

  1. Эта проблема возникает, только если autocapitalizationType - это «предложения», а не для других значений, таких как «слова», «нет».
  2. Я попытался установить autocapitalizationType в коде и в раскадровке с теми же результатами.
  3. Если я не использую метод shouldChangeTextInRange, проблема не воспроизводится. Если я верну true из этого метода, проблема не будет воспроизведена. Поскольку мне нужно выполнить некоторую обработку в этом методе, мне нужно вернуть false.
  4. Тем не менее, чтобы воспроизвести самостоятельно на устройстве до iOS 13, хотя пользователь сообщил об этом на iOS 12.4.1 (на данный момент не проверено).

Может ли кто-нибудь предложить исправление / обходной путь для этой проблемы?


person Krishnabhadra    schedule 17.10.2019    source источник


Ответы (2)


Лучший обходной путь, который я нашел до сих пор, - вместо этого выполнять обработку в textViewDidChange.

Ошибка также обсуждается здесь: Форум разработчиков Apple

person Nikolaj    schedule 23.10.2019
comment
Хм, мне тоже пришлось использовать тот же обходной путь. Это определенно похоже на ошибку Apple. - person Krishnabhadra; 26.10.2019
comment
Баунти-период закончился. Поскольку никакое другое решение не обсуждалось, и мне также пришлось использовать тот же обходной путь, я даю вам награду. Это определенно ошибка Apple. - person Krishnabhadra; 28.10.2019

Попробуйте запланировать этот оператор присваивания в основном цикле:

    textView.text = newString

становится:

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

Это успешно помогло мне решить аналогичную проблему, когда первые две буквы предложения были заглавными. Я предполагаю, что логика прослушивателя didSet для свойства текста UITextView изменилась таким образом, что делегат немедленно запускается синхронно. Асинхронное планирование назначения в основной очереди заставляет / гарантирует возвращение делегата перед тем, как его уволят во второй раз.

person Austin    schedule 05.11.2019
comment
Это приведет к тому, что предложения автозамены перестанут работать. - person user3199693; 27.11.2020