Search code examples
swiftuikit

How can we get the character before cursor?


My code now is:

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

this code works well if the character count is 1, but if it is more than one like the emojis, we can't get it. so how can we get the character if it is emoji or a simple character?


Solution

  • You can simply get the text from the beginning of the document up to the start of the cursor range and get the last character:

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

    If you would like to get the character before the caret without getting the whole text before it you will need to convert the UITextPosition to a String.Index as you can see in my post here offset the index by minus one character and return the character at that 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
        }
    }