Insert string at cursor position of UITextField
I've finally found a solution for this problem! You can put the text you need inserted into the system pasteboard and then paste it at the current cursor position:
[myTextField paste:self]
I found the solution on this person's blog:
http://dev.ragfield.com/2009/09/insert-text-at-current-cursor-location.html
The paste functionality is OS V3.0 specific, but I've tested it and it works fine for me with a custom keyboard.
Update: As per Jasarien's comment below, it is good practice to save off the pasteboard contents first and restore them afterward. For convenience, here is my code:
// Get a reference to the system pasteboard
UIPasteboard* lPasteBoard = [UIPasteboard generalPasteboard];
// Save the current pasteboard contents so we can restore them later
NSArray* lPasteBoardItems = [lPasteBoard.items copy];
// Update the system pasteboard with my string
lPasteBoard.string = @"-";
// Paste the pasteboard contents at current cursor location
[myUIField paste:self];
// Restore original pasteboard contents
lPasteBoard.items = lPasteBoardItems;
[lPasteBoardItems release];
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
How to programmatically enter text in UITextView at the current cursor position
Try this... Inside your button's IBAction
use this (please do not use forced optional unwrapping) or else if the textView has no selection or cursor, the app might crash:
let txt = "whatever you want"
if let range = handleToYourTextView.selectedTextRange {
// From your question I assume that you do not want to replace a selection, only insert some text where the cursor is.
if range.start == range.end {
handleToYourTextView.replaceRange(range, withText: txt)
}
}
How to insert text into UITextField?
You can replace the text as you have done previously and restore the position of your caret. Note that this can only be done with UITextView
rather than UITextField
(that would require a lot more unjustified work, unless you absolutely have to use UITextField
):
NSRange selectionRange = myTextView.selectedRange;
myTextView.text = myNewText;
myTextView.selectedRange = selectionRange;
You have to note that it's a good idea to check the validity of selectionRange
variable for new text - make sure that cursor position isn't greater than the new text length.
Getting the cursor position of UITextField in ios
UITextField
conforms to the UITextInput
protocol which has methods for getting the current selection. But the methods are complicated. You need something like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if (textField.tag == 201) {
UITextRange *selRange = textField.selectedTextRange;
UITextPosition *selStartPos = selRange.start;
NSInteger idx = [textField offsetFromPosition:textField.beginningOfDocument toPosition:selStartPos];
[myclass selectTextForInput:textField atRange:NSMakeRange(idx, 0)];
}
}
Insert text into UITextField at caret Position
The solution was simpler than I thought:
[self insertText:string];
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, string);
This will work properly with selection, caret position et. al.
It will however not use the proper tone when announcing the entered string. VoiceOver uses a deeper voice when announcing inserted text, I put up a separate question on how to control the tone of VoiceOver.
iOS: insert attributed string at cursor for UITextView?
Insert into a mutable copy of the text view’s attributed text by calling https://developer.apple.com/documentation/foundation/nsmutableattributedstring/1414947-insert.
Related Topics
iOS 11 - Unable to Change Navigation Bar Height
Instantiateviewcontrollerwithidentifier - Storyboard Id Set But Still Not Working
Autolayout: Origin and Size Should Change According to Width and Height Factor
Programmatically Detect Dark Mode in Swiftui to Display Appropriate Image
How to Capture Taps Ignored by Wkwebview
Convert Spelled Out Number to Number
How to Integrate Payu Money in Swift
Convert Arabic String to English Number in Swift
How to Detect Fullscreen Mode Using Avplayerviewcontroller in Swift
How to Take Uiimage of Avcapturevideopreviewlayer Instead of Avcapturephotooutput Capture
Parse JSON Response with Afnetworking
A Lighter Way of Discovering Text Writing Direction
Stop Skaction That Repeatsforever - Sprite Kit