32

I have an UITextView in my iPhone app which is editable.

New button is created inside the UITextView whenever user select a specific function.

As the button is always placed on the left side in the text view, I need to position the cursor on the right side of the button so that user can see what they are typing. I can't seem to find a documented (or undocumented) method to set location of the cursor.

Does anybody have any ideas or has anybody else achieved anything similar?

Wayne Chen
  • 185
  • 1
  • 13
GURU
  • 555
  • 2
  • 6
  • 11

6 Answers6

53

I know this is VERY late, but I thought I could help people stuck in this (like me).

The performSelector:withObject:afterDelay seems to work fine (the other answers just wouldn't work for some strange reason):

- (void)textViewDidBeginEditing:(UITextView *)inView 
{ 
[self performSelector:@selector(setCursorToBeginning:) withObject:inView afterDelay:0.01]; 
} 

- (void)setCursorToBeginning:(UITextView *)inView 
{ 
//you can change first parameter in NSMakeRange to wherever you want the cursor to move
inView.selectedRange = NSMakeRange(3, 0); 
} 

source: http://puppenspieler.tumblr.com/post/757819650/set-selectedrange-in-a-uitextview

Cashew
  • 1,406
  • 2
  • 16
  • 21
  • @Cashew this is working but i don't get it, why this is working after delay and not in textViewDidBeginEditing method ? can you tell me why this is not working directly in the method...give you +1 for solution.... – Sam Apr 05 '14 at 10:16
  • @Sam no idea, this is just a way I found to hack it. This might stop working as Apple updates their SDK – Cashew Apr 05 '14 at 20:06
  • For Swift, to pass multiple arguments to a selector after a delay, use @Matt's delay method here: http://stackoverflow.com/questions/24034544/dispatch-after-gcd-in-swift/24318861#24318861 – ObjectiveTC Aug 01 '15 at 23:25
23
textView.editable = YES;
textView.selectedRange = NSMakeRange(2, 0);

Set the selectedRange to a location with length of 0 and you probably also want the textView to be editable so also set that to YES.

Evan
  • 5,831
  • 1
  • 22
  • 43
18

Try something like this:

dispatch_async(dispatch_get_main_queue(), ^{
    inView.selectedRange = NSMakeRange(3, 0);
});

This will cause selectedRange to be executed on the main thread at the beginning of the next runloop.

acavanagh
  • 181
  • 2
  • 4
7

I use the following to get to the beginning of the textView, using Swift 4:

DispatchQueue.main.async {
    self.selectedTextRange = self.textRange(from: self.beginningOfDocument, to: self.beginningOfDocument)
}
blwinters
  • 1,634
  • 16
  • 34
3

change selectedRange of your textView. for example to place cursor at position 3:

[textView setSelectedRange:NSMakeRange(3, 0)];

In your case, added some spaces on the textView contents might helps. and observer textview 's textDidChanged event to prevent these space will be deleted by user.

xhan
  • 5,610
  • 4
  • 31
  • 47
  • I inserted this code in textViewDidBeginEditing but it's not working. The position of the cursor in the text view still being on the left side. – GURU Jan 17 '12 at 07:49
  • is no content inside your textView? added some spaces before set cursor position. – xhan Jan 17 '12 at 07:58
0

If you want to make Texview placeholder is required or optional like me. See my hack

 func textViewDidBeginEditing(textView: UITextView) {
        if textView.text.isEmpty {
          if self.text == "Required" || self.text == "Optional" {
            dispatch_async(dispatch_get_main_queue(), {
              textView.selectedRange = NSMakeRange(0, 0)
            });
          }
        }
      }

      func textViewDidEndEditing(textView: UITextView) {
        if CommonUtils.isEmptyString(textView.text) {
          if required {
            textView.text = "Required"
          } else {
            textView.text = "Optional"
          }
          textView.textColor = grayColor//
        }
      }

      func textViewDidChange(textView: UITextView) {
        if textView.text.isEmpty {
          if required {
            textView.text = "Required"
          } else {
            textView.text = "Optional"
          }
          textView.textColor = grayColor
          textView.selectedRange = NSMakeRange(0, 0)
        } else {
          if required {
            if textView.text.length > "Required".length {
              textView.text = self.text.replace("Required", withString: "")
            }
          } else {
            if textView.text.length > "Optional".length {
              textView.text = self.text.replace("Optional", withString: "")
            }
          }
          textView.textColor = blackColor//
        }
      }

Dont forget to register delegate: UITextViewDelegate

Rico Nguyen
  • 183
  • 3
  • 8