Ottenere e impostare la posizione del cursore di UITextField e UITextView in Swift


109

Ho sperimentato UITextFielde come lavorare con la posizione del cursore. Ho trovato una serie di risposte di relazione Objective-C, come in

Ma dal momento che lavoro con Swift, volevo imparare come ottenere la posizione corrente del cursore e impostarla anche in Swift.

La risposta che segue è il risultato della mia sperimentazione e traduzione da Objective-C.

Risposte:


316

Il contenuto seguente si applica a entrambi UITextFielde UITextView.

Informazioni utili

L'inizio del testo del campo di testo:

let startPosition: UITextPosition = textField.beginningOfDocument

La fine del testo del campo di testo:

let endPosition: UITextPosition = textField.endOfDocument

La gamma attualmente selezionata:

let selectedRange: UITextRange? = textField.selectedTextRange

Ottieni la posizione del cursore

if let selectedRange = textField.selectedTextRange {

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

    print("\(cursorPosition)")
}

Imposta la posizione del cursore

Per impostare la posizione, tutti questi metodi stanno effettivamente impostando un intervallo con gli stessi valori di inizio e fine.

All'inizio

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

All'estremità

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

A una posizione a sinistra della posizione corrente del cursore

// 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 posizione arbitraria

Inizia dall'inizio e sposta 5 caratteri a destra.

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

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

Relazionato

Seleziona tutto il testo

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

Seleziona un intervallo di testo

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

Inserisce il testo nella posizione corrente del cursore

textField.insertText("Hello")

Appunti

  • Utilizzare textField.becomeFirstResponder()per evidenziare il campo di testo e far apparire la tastiera.

  • Vedi questa risposta per come ottenere il testo in un certo intervallo.

Guarda anche


Qual è lo scopo di startPosition? Cosa puoi farci? Inoltre qual è lo scopo che potrebbe essere necessario per ottenere la posizione del cursore?
Tesoro

2
@ Honey, ho usato il nome della variabile per fare riferimento a due cose diverse qui. Il primo era fare riferimento all'inizio del campo di testo. Sarebbe utile se volessi spostare il cursore lì. Il secondo era riferirsi all'accattonaggio di un intervallo di testo selezionato. È utile se vuoi copiare quell'intervallo o impostare qualche attributo su di esso.
Suragch,

C'è qualcosa per spostare il cursore a destra mentre il campo di testo è vuoto? Ho seguito la tua risposta ma non sono riuscito a farcela.
Yucel Bayram

1
@yucelbayram, puoi posizionare il cursore dopo la H usando textField.endOfDocument. Puoi anche utilizzare trattini bassi o spazi per rappresentare le lettere mancanti.
Suragch

1
@ArielSD, mi dispiace, non ci lavoro da un po '. Non ricordo
Suragch

42

nel mio caso ho dovuto usare DispatchQueue:

func textViewDidBeginEditing(_ textView: UITextView) {

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

nient'altro da questo e altri thread ha funzionato.

PS: Ho ricontrollato su quale thread fosse in esecuzione textViewDidBeginEditing, ed era thread principale, poiché tutta l'interfaccia utente dovrebbe funzionare, quindi non sono sicuro del motivo per cui quel piccolo ritardo usando main.asynch ha funzionato.


2
Non è un ritardo ma il prossimo ciclo di esecuzione. Molto probabilmente l'intervallo selezionato del campo di testo viene modificato dalla stessa funzione che ha chiamato textViewDidBeginEditing. Quindi mettendolo in coda, accadrà dopo che il chiamante ha finito.
Michael Ozeryansky

@MichaelOzeryansky Sì, lo penso anch'io. Ma questo pone la domanda: qual è il metodo giusto per impostare manualmente la posizione del cursore?
timowonder

ha funzionato questa soluzione anche nel mio caso
Hattori Hanzō

1

Per impostare la posizione del cursore nel punto:

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

Per ripristinare la posizione del cursore:

textView.endFloatingCursor()

Nota : questo esempio funziona sia in Textview che in Textfield.


@ Suragch Floating Cursor è un metodo per impostare la posizione del cursore in textView o textField.
Parth Patel

1
let range = field.selectedTextRange

field.text = "hello world"

field.selectedTextRange = range 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.