Search code examples
objective-ccursoruitextview

Move Cursor to Location Objective-C


I have a UITextView and I want have two buttons. When the user taps the back button I want the cursor to move back 1 character. When they tap to forward button the cursor should move forward 1 character. How could I do this?


Solution

  • I wrote it out for you, referencing the answer linked below. You can drop the code I wrote into a basic project and try it out.

    The solution idea:

    You can programmatically select a block of text by specifying the range of text to select (see reference). What's a range, you ask? It's basically a starting position and a length. Since you only care about the cursor position, you can ignore the length (i.e. keep it at zero) and adjust the starting position of the "selection" by +1 or -1.

    Reference:

    Can I select a specific block of text in a UITextField?

    Code Explanation:

    In the code below, there are two buttons (Forward and Back) and a target method for each of them that changes the cursor position in the UITextView. Note that tv is the class variable/property for your UITextView (and needs to be declared as such).

    The Code:

    - (void)viewDidLoad {
        [super viewDidLoad];
        UIButton *forward = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        forward.frame = CGRectMake(20, 20, 100, 50);
        [forward setTitle:@"Forward" forState:UIControlStateNormal];
        [forward addTarget:self action:@selector(moveForward:) forControlEvents:UIControlEventTouchUpInside];
    
        UIButton *back = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        back.frame = CGRectMake(130, 20, 100, 50);
        [back setTitle:@"Back" forState:UIControlStateNormal];    
        [back addTarget:self action:@selector(moveBack:) forControlEvents:UIControlEventTouchUpInside];
    
        tv = [[UITextView alloc] initWithFrame:CGRectMake(20, 120, 280, 100)];
        [self.view addSubview:forward];
        [self.view addSubview:back];
        [self.view addSubview:tv];    
    }
    
    
    -(void)moveForward:(id)sender {
        UITextRange *selectedRange = [tv selectedTextRange];
        // Calculate the new position, - for left and + for right
    
        if (tv.selectedRange.location < tv.text.length) {
            UITextPosition *newPosition = [tv positionFromPosition:selectedRange.start offset:1];
    
            UITextRange *newRange = [tv textRangeFromPosition:newPosition toPosition:newPosition];
    
            // Set new range
            [tv setSelectedTextRange:newRange];
        }
    }
    
    -(void)moveBack:(id)sender {
        UITextRange *selectedRange = [tv selectedTextRange];
        // Calculate the new position, - for left and + for right
    
        if (tv.selectedRange.location > 0) {
            UITextPosition *newPosition = [tv positionFromPosition:selectedRange.start offset:-1];
    
            UITextRange *newRange = [tv textRangeFromPosition:newPosition toPosition:newPosition];
    
            // Set new range
            [tv setSelectedTextRange:newRange];
        }
    }