Swift 我们怎样才能得到光标前的字符?

Swift 我们怎样才能得到光标前的字符?,swift,uikit,Swift,Uikit,我现在的代码是: extension UITextView { func characterBeforeCursor() -> String? { // get the cursor position if let cursorRange = self.selectedTextRange { // get the position one character before the cursor start position

我现在的代码是:

extension UITextView {
    func characterBeforeCursor() -> String? {

        // get the cursor position
        if let cursorRange = self.selectedTextRange {

            // get the position one character before the cursor start position
            if let newPosition = self.position(from: cursorRange.start, offset: -1) {

                let range = self.textRange(from: newPosition, to: cursorRange.start)
                return self.text(in: range!)
            }
        }
        return nil
    }
}

如果字符计数为1,则此代码运行良好,但如果像emojis一样不止一个,则无法获得它。那么,如果是表情符号或简单字符,我们如何获取该字符呢?

您只需获取从文档开始到光标范围开始的文本,并获取最后一个字符:

extension UITextView {
    var characterBeforeCaret: Character? {
        if let selectedTextRange = self.selectedTextRange,
           let range = textRange(from: beginningOfDocument, to: selectedTextRange.start) {
            return text(in: range)?.last
        }
        return nil
    }
}
如果您希望在插入符号之前获取字符而不在其之前获取整个文本,则需要将
UITextPosition
转换为
String.Index
,正如您在我的文章中看到的那样,将索引偏移减一个字符,然后返回该索引处的字符:

extension UITextView {
    var characterBeforeCaret: Character? {
        if let textRange = self.selectedTextRange,
            let start = Range(.init(location: offset(from: beginningOfDocument, to: textRange.start), length: 0), in: text)?.lowerBound,
            let index = text.index(start, offsetBy: -1, limitedBy: text.startIndex) {
            return text[index]
        }
        return nil
    }
}

您只需获取从文档开始到光标范围开始的文本,并获取最后一个字符:

extension UITextView {
    var characterBeforeCaret: Character? {
        if let selectedTextRange = self.selectedTextRange,
           let range = textRange(from: beginningOfDocument, to: selectedTextRange.start) {
            return text(in: range)?.last
        }
        return nil
    }
}
如果您希望在插入符号之前获取字符而不在其之前获取整个文本,则需要将
UITextPosition
转换为
String.Index
,正如您在我的文章中看到的那样,将索引偏移减一个字符,然后返回该索引处的字符:

extension UITextView {
    var characterBeforeCaret: Character? {
        if let textRange = self.selectedTextRange,
            let start = Range(.init(location: offset(from: beginningOfDocument, to: textRange.start), length: 0), in: text)?.lowerBound,
            let index = text.index(start, offsetBy: -1, limitedBy: text.startIndex) {
            return text[index]
        }
        return nil
    }
}

问题是,这里有不同的坐标系,你不能以错误的方式混淆它们


  • 如果你说
    selectedRange
    ,你就进入了Objective-C可可的世界。您使用的是NSRange,它完全以UTF16代码点度量,而表情符号由多个UTF16代码点组成。例如,
    长度
    “这是一个测试问题是,这里有不同的坐标系,你不能以错误的方式混淆它们


    • 如果你说
      selectedRange
      ,你就是在Objective-C Cocoa的世界里。你使用的是一个NSRange,它完全是用UTF16码点来衡量的,一个表情符号由多个UTF16码点组成。例如,
      长度
      “这是一个测试,这是我想要的。OP最初尝试的错误在于它有效地混合了两种不同的坐标系对,这就是我的意思。OP最初尝试的错误在于它有效地混合了两种不同的坐标系@我的观点是这不会影响我的答案。我只是泛泛地谈论OP遇到的问题所引发的16位代码点、字符和快速字符串的问题。我希望这篇小文章对不了解这一点的未来读者有用。那不是你。(我想在出现快捷字符串之前,我本可以谈论我们过去对这个问题所做的事情,但我再也不关心这个问题了。)@LeoDabus我的观点是,这不会影响我的答案。我只是泛泛地谈论OP遇到的问题所引发的16位代码点、字符和快速字符串的问题。我希望这篇小文章对不了解这一点的未来读者有用。那不是你。(我想在出现快捷字符串之前,我本可以谈谈我们过去对这个问题所做的工作,但我再也不关心这个问题了。)