UITextField получить редактируемое слово

Я работаю над компонентом автозаполнения, и у меня есть одна проблема, которую я хотел бы решить простым способом.

Я хочу поддержать редактирование автозаполненного текста, например:

 blablabl @usertag blablabl

Если пользователь возвращается и редактирует строку @usertag, я хотел бы запустить автозаполнение, когда оно будет отредактировано.

Вопрос в том, как получить отредактированное слово из текстового поля. Я думал о том, чтобы занять позицию курсора, отделить строку nsstring от слова " " (пробел) и посчитать буквы от первого слова до позиции курсора.

Есть ли более простой способ сделать это?

3 ответа

Решение

Хорошо, я нашел способ сделать это довольно легко. Может быть, кто-то найдет это полезным:

UITextRange* selectedRange = [textField selectedTextRange];
NSInteger cursorOffset = [textField offsetFromPosition:0 toPosition:selectedRange.start];
NSString* text = textField.text;
NSString* substring = [text substringToIndex:cursorOffset];
NSString* editedWord = [[substring componentsSeparatedByString:@" "] lastObject];

Решение Swift4

   func getCurrentEditingWord() ->String? {
        let selectedRange: UITextRange? = self.textView.selectedTextRange
        var cursorOffset: Int? = nil
        if let aStart = selectedRange?.start {
            cursorOffset = self.textView.offset(from: self.textView.beginningOfDocument, to: aStart)
        }
        let text = self.textView.text
        let substring = (text as NSString?)?.substring(to: cursorOffset!)
        let editedWord = substring?.components(separatedBy: " ").last
        return editedWord
    }

Вот решение для любителей эффективности. Написано на Swift 4.2. Я утверждаю, что это более эффективно, потому что другие ответы вызывают метод StringString.componentкоторый без необходимости преобразует всю подстроку в массив. Кроме того, эти решения всегда захватывают слова перед курсором, которые не обязательно могут быть текущим словом.

extension UITextView {
    /// Returns the current word that the cursor is at.
    func currentWord() -> String {
        guard let cursorRange = self.selectedTextRange else { return "" }
        func getRange(from position: UITextPosition, offset: Int) -> UITextRange? {
            guard let newPosition = self.position(from: position, offset: offset) else { return nil }
            return self.textRange(from: newPosition, to: position)
        }
    
        var wordStartPosition: UITextPosition = self.beginningOfDocument
        var wordEndPosition: UITextPosition = self.endOfDocument
    
        var position = cursorRange.start
    
        while let range = getRange(from: position, offset: -1), let text = self.text(in: range) {
            if text == " " || text == "\n" {
                wordStartPosition = range.end
                break
            }
            position = range.start
        }
    
        position = cursorRange.start
    
        while let range = getRange(from: position, offset: 1), let text = self.text(in: range) {
            if text == " " || text == "\n" {
                wordEndPosition = range.start
                break
            }
            position = range.end
        }
    
        guard let wordRange = self.textRange(from: wordStartPosition, to: wordEndPosition) else { return "" }
    
        return self.text(in: wordRange) ?? ""
    }
}

Вы пробовали использовать доступные методы UITextFieldDelegate? Если вы хотите получить доступ к слову при редактировании, вы можете просто использовать -textField:shouldChangeCharactersInRange:replacementString: Внутри этого метода у вас есть доступ к строке по мере ее ввода, и вы также можете выполнять любые манипуляции со строками для каждого нового введенного символа.

Другие вопросы по тегам