Obteniendo y Configurando la Posición del Cursor de UITextField y UITextView en Swift

He estado experimentando con UITextField y cómo trabajar con su posición de cursor. He encontrado una serie de respuestas relacionadas con Objective-C, como en

  • Obteniendo la posición del cursor de UITextField en ios
  • Controlar la posición del cursor en UITextField
  • UITextField obtiene la palabra editada actualmente

Pero dado que estoy trabajando con Swift, quería aprender a obtener la ubicación actual del cursor y también configurarlo en Swift.

La respuesta a continuación es el resultado de mi experimentación y traducción de Objective-C.

Esta respuesta ha sido actualizada para Swift 3

El siguiente contenido se aplica a UITextField y UITextView .

Información útil

El comienzo mismo del texto del campo de texto:

 let startPosition: UITextPosition = textField.beginningOfDocument 

El final del texto del campo de texto:

 let endPosition: UITextPosition = textField.endOfDocument 

El rango seleccionado actualmente:

 let selectedRange: UITextRange? = textField.selectedTextRange 

Obtener la posición del cursor

 if let selectedRange = textField.selectedTextRange { let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start) print("\(cursorPosition)") } 

Establecer la posición del cursor

Para establecer la posición, todos estos métodos en realidad están configurando un rango con los mismos valores de inicio y fin.

Al Principio

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

Hasta el final

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

A una posición a la izquierda de la posición actual del cursor

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

A una posición arbitraria

Comience por el principio y mueva 5 caracteres a la derecha.

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

Relacionado

Seleccionar todo el texto

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

Seleccione un rango de texto

 // 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!) } 

Insertar texto en la posición actual del cursor

 textField.insertText("Hello") 

Notas

  • Use textField.becomeFirstResponder() para enfocar el campo de texto y hacer que aparezca el teclado.

  • Vea esta respuesta para saber cómo obtener el texto en algún rango.

Ver también

  • Cómo crear un rango en Swift

en mi caso, tuve que usar DispatchQueue:

 func textViewDidBeginEditing(_ textView: UITextView) { DispatchQueue.main.async{ textField.selectedTextRange = ... } } 

nada más de este y otros hilos funcionó.

PD: Comprobé dos veces en qué subproceso se estaba ejecutando textViewDidBeginEditing, y era el hilo principal, ya que toda la IU debería ejecutarse, por lo que no estoy seguro de por qué funcionó ese pequeño retraso con main.asynch.