Search code examples
objective-ccocoa-touchuikituitextviewuitextrange

How to get offset from start of line of UITextRange.start


I have an UITextView which can have multiple lines. All I'm interested in is the position of the cursor on a certain line (where it doesn't matter whether first, second, third line etc.).

I've been logging UITextRange.start which gives me exactly what I need, namely the offset property:

cp <UITextPositionImpl: 0x6e93260> <<WebVisiblePosition: 0x6e92d00>(offset=5, context=([d|], [u+0064|u+0000])>

My question is how I get the offset=5 into a simply integer?

Here is my code:

UITextRange *caretPositionRange = textView.selectedTextRange;
NSLog(@"cp %@", caretPositionRange.start);

All I need would be something like int cp = caretPositionRange.start.offset which doesn't work.


edit:

to clarify, I'm particularly interested in the cursor position of each line, not the entire TextView. So this won't really work:

UITextRange *caretPositionRange = tv.selectedTextRange;
    int caretPosition = [tv offsetFromPosition:tv.beginningOfDocument
                            toPosition:caretPositionRange.start];

as this would give me a different position for each line.


edit 2:

the answer below given by Jesse works really well. First time around, I got an EXC_BAD_EXCESS as I didn't check if startOfLine = nil, so keep in mind checking if it's not nil.


Solution

  • You'll need to ask the UITextView via its UITextInput methods. Something like this:

    UITextPosition *pos = caretPositionRange.start;
    id<UITextInputTokenizer> tokenizer = [textView tokenizer];
    UITextPosition *startOfLine = [tokenizer positionFromPosition:pos 
                                                       toBoundary:UITextGranularityLine
                                                     inDirection:UITextStorageDirectionBackward];
    if (startOfLine != nil) {
        // based on some experiments, startOfLine may be nil for, eg, empty text views
        // the next line crashes if you pass nil, so we check first
        NSUInteger offset = [textView offsetFromPosition:startOfLine
                                              toPosition:pos];
    }