Getting and Setting Cursor Position of UITextField and UITextView in Swift
The following content applies to both UITextField
and UITextView
.
Useful information
The very beginning of the text field text:
let startPosition: UITextPosition = textField.beginningOfDocument
The very end of the text field text:
let endPosition: UITextPosition = textField.endOfDocument
The currently selected range:
let selectedRange: UITextRange? = textField.selectedTextRange
Get cursor position
if let selectedRange = textField.selectedTextRange {
let cursorPosition = textField.offset(from: textField.beginningOfDocument, to: selectedRange.start)
print("\(cursorPosition)")
}
Set cursor position
In order to set the position, all of these methods are actually setting a range with the same start and end values.
To the beginning
let newPosition = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
To the end
let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
To one position to the left of the current cursor position
// 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)
}
}
To an arbitrary position
Start at the beginning and move 5 characters to the right.
let arbitraryValue: Int = 5
if let newPosition = textField.position(from: textField.beginningOfDocument, offset: arbitraryValue) {
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
}
Related
Select all text
textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)
Select a range of text
// 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!)
}
Insert text at the current cursor position
textField.insertText("Hello")
Notes
Use
textField.becomeFirstResponder()
to give focus to the text field and make the keyboard appear.See this answer for how to get the text at some range.
See also
- How to Create a Range in Swift
UITextField set cursor to start text position
Set your view controller (or some other appropriate object) as the text field's delegate
and implement the textFieldDidBeginEditing:
method like this:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
UITextPosition *beginning = [textField beginningOfDocument];
[textField setSelectedTextRange:[textField textRangeFromPosition:beginning
toPosition:beginning]];
}
Note that setSelectedTextRange:
is a protocol method of UITextInput
(which UITextField
implements), so you won't find it directly in the UITextField
documentation.
Moving cursor at beginning UItextview
This works in my testing on the iOS 6.0 simulator:
- (void)textViewDidBeginEditing:(UITextView *)textView {
dispatch_async(dispatch_get_main_queue(), ^{
textView.selectedRange = NSMakeRange(0, 0);
});
}
I guess it updates the selection based on the touch location after it sends the textViewDidBeginEditing:
message. The dispatch_async
works around that.
Can't move cursor in UITextField
The answer here was exactly what @juanreyesv pointed out in the comments! becomeFirstResponder
call was moved to viewDidAppear
rather than viewWillAppear
and now it's working!
Cursor at the start of UITextField
Try this instead:
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == self.textName{
let beginning = textField.beginningOfDocument
textField.selectedTextRange = textField.textRange(from: beginning, to: beginning)
}
}
So remove textEmail.becomeFirstResponder()
and use textField.textRange
instead of textEmail.textRangeFromPosition
.
And inside of the textFieldDidBeginEditing
function use the parameter textField
as shown in my example above.
UITextField starting cursor position is wrong
You need to always update your UI from the main thread:
DispatchQueue.main.async {
textField.selectedTextRange = textField.textRange(from: textField.endOfDocument, to: textField.endOfDocument)
}
Related Topics
Error: Error Domain=Nsurlerrordomain Code=-1001 "The Request Timed Out."
-Canopenurl: Failed for Url: "Fbauth2:/" (Osstatus Error -10814.)"
What Is the "Right" Way to Handle Orientation Changes in iOS 8
Custom Uitableviewcell Programmatically Using Swift
Auto-Layout: What Creates Constraints Named Uiview-Encapsulated-Layout-Width & Height
Black Screen After Adding Scenedelegate and Updating Info.Plist
How to Set Uibutton Background Color Forstate: Uicontrolstate.Highlighted in Swift
Change Button Background Color Using Swift Language
Spritekit - Not Loading @3X Images from Sktextureatlas
Capture Redirect Url in Wkwebview in iOS
Removing Duplicates from Array of Custom Objects Swift
How to Lookup a String Constant at Runtime in Objective-C
Programmatically Scroll a Uiscrollview
Alternative iOS Layouts for Portrait and Landscape Using Just One .Xib File
Why Push Notifications Is Not Working on Testflight
Correct Implementation of Parent/Child Nsmanagedobjectcontext