在UITextView中按字删除幻灯片到类型在`shouldChangeText`委托方法中给出了不正确的范围

问题描述 投票:1回答:1

我在ViewController中有一个UITextView。我已经从UITextViewDelegate实现了shouldChangeTextInRange委托方法。我通过上述委托方法获得的用于删除单个字符的range值类似于{location,1}

但是如果我在执行删除操作之前使用滑入式机制插入单词,则会删除整个单词,而不是单个字符。我需要对此进行跟踪。

例如,我使用幻灯片类型机制插入“ Hello”。如果按键盘上的Delete键,则会得到{4,1}作为范围,但是在文本视图中整个单词“ Hello”已被删除。在这种情况下,我需要将范围设置为{0,5},就像选择文本“ Hello”并删除它一样。

是否有办法区分普通删除操作和幻灯片到类型的删除操作?如何获得在文本视图中已删除的实际范围?

非常感谢您的帮助。

这是我尝试过的。

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.addTextView()
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
}

extension ViewController {
    func addTextView() {
        let textContainer = NSTextContainer(size: CGSize(width: 200, height: CGFloat.greatestFiniteMagnitude))

        let layoutManager = NSLayoutManager()
        layoutManager.addTextContainer(textContainer)

        let textStorage = NSTextStorage()
        textStorage.delegate = self
        textStorage.addLayoutManager(layoutManager)

        let textViewFrame = CGRect(x: 50, y: 50, width: 200, height: 200)
        let textView = UITextView(frame: textViewFrame, textContainer: textContainer)
        textView.backgroundColor = .green
        textView.delegate = self

        self.view.addSubview(textView)
    }
}

extension ViewController: UITextViewDelegate {
    func textViewDidBeginEditing(_ textView: UITextView) {
        print("text editing began")
    }

    func textViewDidChange(_ textView: UITextView) {
        print("text view content changed")
    }

    func textViewDidChangeSelection(_ textView: UITextView) {
        print("text view selection changed")
    }

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        print("should change \(text) in \(range)")
        return true
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        print("text editing ended")
    }
}

extension ViewController: NSTextStorageDelegate {
    func textStorage(_ textStorage: NSTextStorage, willProcessEditing editedMask: NSTextStorage.EditActions, range editedRange: NSRange, changeInLength delta: Int) {
        print("will process \(editedRange)")
    }

    func textStorage(_ textStorage: NSTextStorage, didProcessEditing editedMask: NSTextStorage.EditActions, range editedRange: NSRange, changeInLength delta: Int) {
        print("did process \(editedRange)")
    }
}

编辑1:

我有一个独立的存储机制,我可以根据该存储机制根据shouldChangeText委托方法中提供的范围和替换文本来更新对文本视图的更改。为了简单起见,我没有将其包括在内。

ios swift uitextview uitextviewdelegate nstextstorage
1个回答
0
投票

我只是注意到了完全相同的一件事,并且努力了好一阵子,试图以一种优雅的方式解决这个问题。在我看来,这必须是一个错误,因此希望它将尽快得到解决。提交提出的解决方案后,我将向Apple提交错误报告。

// Variable to keep track of when a word might have been deleted
fileprivate var didJustDelete = false


func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
  if text.count > 0 {
    // Code to handle adding text
    ...
  } else {
    // Code to handle deleting text
    didJustDelete = true
    ...
  }
}


func textViewDidChange(_ textView: UITextView) {
  // Check for deleting an entire word
  if didJustDelete {
    didJustDelete = false

    let difference = actualText.count - textView.text.count
    if difference > 0 {
      // Code to handle deleting a word
      let range = NSRange(location: textView.text.count, length: difference)
      ...
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.