Получение и установка положения курсора UITextField и UITextView в Swift

109

Я экспериментировал UITextFieldи как работать с положением курсора. Я нашел несколько ответов Objective-C, например

Но поскольку я работаю со Swift, я хотел узнать, как получить текущее местоположение курсора, а также установить его в Swift.

Ответ ниже является результатом моих экспериментов и перевода из Objective-C.

Suragch
источник

Ответы:

317

Следующее содержимое относится как к, так UITextFieldи к UITextView.

Полезная информация

Самое начало текста текстового поля:

let startPosition: UITextPosition = textField.beginningOfDocument

Самый конец текста текстового поля:

let endPosition: UITextPosition = textField.endOfDocument

Текущий выбранный диапазон:

let selectedRange: UITextRange? = textField.selectedTextRange

Получить позицию курсора

if let selectedRange = textField.selectedTextRange {

    let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)

    print("\(cursorPosition)")
}

Установить позицию курсора

Чтобы установить позицию, все эти методы фактически устанавливают диапазон с одинаковыми начальными и конечными значениями.

К началу

let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)

К концу

let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)

На одну позицию слева от текущей позиции курсора

// only if there is a currently selected range
if let selectedRange = textField.selectedTextRange {

    // and only if the new position is valid
    if let newPosition = textField.position(from: selectedRange.start, offset: -1) {

        // set the new position
        textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
    }
}

В произвольную позицию

Начните с начала и переместите 5 символов вправо.

let arbitraryValue: Int = 5
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: arbitraryValue) {

    textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}

Связанный

Выбрать весь текст

textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)

Выберите диапазон текста

// Range: 3 to 7
let startPosition = textField.position(from: textField.beginningOfDocument, offset: 3)
let endPosition = textField.position(from: textField.beginningOfDocument, offset: 7)

if startPosition != nil && endPosition != nil {
    textField.selectedTextRange = textField.textRange(from: startPosition!, to: endPosition!)
}

Вставить текст в текущую позицию курсора

textField.insertText("Hello")

Ноты

  • Используйте, textField.becomeFirstResponder()чтобы выделить текстовое поле и отобразить клавиатуру.

  • См. Этот ответ, чтобы узнать, как получить текст в некотором диапазоне.

Смотрите также

Suragch
источник
Какова цель startPosition? Что ты можешь сделать с этим? Также для чего может понадобиться получить позицию курсора?
Дорогая,
2
@Honey, я использовал это имя переменной для обозначения здесь двух разных вещей. Первый - это ссылка на начало текстового поля. Было бы полезно, если бы вы хотели переместить туда курсор. Второй - относиться к началу выбранного диапазона текста. Это полезно, если вы хотите скопировать этот диапазон или установить для него какой-либо атрибут.
Suragch
Есть ли что-нибудь, чтобы переместить курсор вправо, пока текстовое поле пусто? Я последовал твоему ответу, но не смог.
Yucel Bayram
1
@yucelbayram, Вы можете поставить курсор после H с помощью textField.endOfDocument. Вы также можете использовать подчеркивания или пробелы для обозначения пропущенных букв.
Suragch
1
@ArielSD, извини, я давно над этим не работал. Я не помню.
Suragch
42

в моем случае мне пришлось использовать DispatchQueue:

func textViewDidBeginEditing(_ textView: UITextView) {

   DispatchQueue.main.async{
      textField.selectedTextRange = ...
   }
}

больше ничего из этого и других потоков не работало.

PS: Я дважды проверил, в каком потоке работал textViewDidBeginEditing, и это был основной поток, так как весь пользовательский интерфейс должен работать, поэтому не уверен, почему эта небольшая задержка с использованием main.asynch сработала.

Майкл Рос
источник
2
Это не задержка, а следующий цикл выполнения. Скорее всего, выбранный диапазон текстового поля изменяется той же функцией, которая вызвала textViewDidBeginEditing. Таким образом, помещая его в очередь, это произойдет после того, как вызывающий абонент закончит.
Михаил Озерянский
@MichaelOzeryansky Да, я тоже так думаю. Но возникает вопрос - какой метод является правильным для установки положения курсора вручную?
timetowonder
работал это решение в моем случае, а также
Хаттори Ханзо
1

Чтобы установить положение курсора в вашей точке:

textView.beginFloatingCursor(at: CGPoint(x: 10.0, y: 10.0))

Для сброса позиции курсора:

textView.endFloatingCursor()

Примечание . Этот пример работает как в Textview, так и в Textfield.

Парт Патель
источник
@Suragch Floating Cursor - это один из методов установки положения курсора в textView или textField.
Parth Patel
1
let range = field.selectedTextRange

field.text = "hello world"

field.selectedTextRange = range 
Иван
источник