0

我有问题。鉴于我有一个 UITextField 一个按钮来删除文本字段的内容。

所以这可以按预期工作:

  1. 用键盘输入文字
  2. 点击删除按钮
  3. 用三个手指点击并从上下文菜单中选择撤消
  4. 文字再次出现

现在使用听写时事情开始变得很奇怪:

  1. 点击听写按钮
  2. 说出一些单词,以便它们出现在文本字段中
  3. 点击删除按钮
  4. 用三个手指点击并从上下文菜单中选择撤消
  5. 应用程序崩溃

崩溃是Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray replaceObjectsInRange:withObject:length:: Out of bounds'

因此,听写中的文本似乎并未出现在可能的撤消列表中。有没有人知道如何解决这个问题?到目前为止我尝试了什么:

  • 使用基本代码清理应用程序以进行验证(请参阅本文末尾的代码)
  • 创建 UITextField 的子类以func dictationRecordingDidEnd()使用文本覆盖和注册新的撤消
  • 挠了挠我的头,想知道为什么

我很乐意在这里找到解决方案!

测试应用的代码示例:

import UIKit

class ViewController: UIViewController {

    let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 44))

    override func viewDidLoad() {
        super.viewDidLoad()

        textField.layer.borderColor = UIColor.black.cgColor
        textField.layer.borderWidth = 1
        view.addSubview(textField)

        let deletebutton = UIButton(type: .custom)
        deletebutton.frame = CGRect(x: 50, y: 100, width: 100, height: 50)
        deletebutton.addTarget(self, action: #selector(deleteText(_:)), for: .touchUpInside)
        deletebutton.setTitle("delete", for: .normal)
        deletebutton.setTitleColor(.black, for: .normal)
        view.addSubview(deletebutton)
    }

    @objc func deleteText(_ sender: UIButton) {
        textField.text = nil
    }
}

更新 1

我现在通过设置将清除按钮添加到文本字段textField.clearButtonMode = .whileEditing,这可以按预期工作。所以主要问题是:内置清除按钮与自定义按钮有什么不同?是否触发了一些通知?还有什么魔法?请赐教!

更新 2

执行此操作时应用程序也会崩溃:

  1. 规定某事
  2. 使用不同的文本替换文本textField.text = "Something"
  3. 三指点击并选择撤消
4

1 回答 1

0

由于那里还没有答案,我会在找到解决方案时回答它。

我可以回答为什么会发生这种情况,但这种行为似乎很常见的是,这种行为会使 App Store 中广泛使用和可用的应用程序崩溃。

无论如何,以下代码将防止崩溃,并且基于此处列出的答案:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text else {
            return true
        }

        let str = text + string
        guard str.count > 0 else {
            return false
        }

        if string.isEmpty && range.length > 0 {
            textField.text = text.count > range.length ? String(text.dropLast(range.length)) : ""
            return false
        }
        return true
    }

我很乐意帮助其他人回答这个问题!

于 2020-09-23T11:44:59.013 回答