iosuitextviewuitextinputuitextposition

How can I get the current selected line number inside UITextView?


I am using the below written method for getting the current selected line number of textView having attributed text. It works fine if last line is not blank. If last line goes blank this method is not giving a proper line number. 

Method : 

    - (NSInteger)getCurrentLineIndex{
        /*
         Get Current Line Inside UITextView
         */
        CGPoint cursorPosition = [self caretRectForPosition:self.selectedTextRange.start].origin;
        return (NSInteger)(cursorPosition.y / self.font.lineHeight);
    }

Is there any other way to get the current line index?


Fixed :  I already had mRangesArray in which each object gave a range of each line. Using those range objects and comparing with the selected range, I was able to fix the problem.

1) Get Ranges Array - (void)analyse { if (self.mRangesArray != nil) { [self.mRangesArray removeAllObjects]; } NSString *string = self.text; NSUInteger numberOfLines, index, stringLength = [string length];

    NSMutableArray *ranges = [NSMutableArray new];
    for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
    {
        NSRange range = [string lineRangeForRange:NSMakeRange(index, 0)];
        [ranges addObject:[NSValue valueWithRange:range]];
    }
    if (self.mRangesArray == nil) {
        self.mRangesArray = [[NSMutableArray alloc]init];
    }
    self.mRangesArray = ranges;
}

2) Compare Range Objects inside the RangesArray with the current selected Range
- (NSInteger)getCurrentLineIndex{ /* This method will be used to get mRangesArray */ [self analyse];

    /*
     Get Current Line Inside UITextView
     */

    NSRange selectedRange = self.selectedRange;

   __block NSInteger index = [self.mRangesArray count]-1;
    [self.mRangesArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSRange objectRange = [obj rangeValue];
        if (*stop == NO) {
            if (NSLocationInRange(selectedRange.location, objectRange)) {
                index = idx;
                *stop =YES;
                return;
              }
        }
    }];

}

Thanks guys for your help. Cheers :)


Solution

  • EDIT: I've obviously ignored the currently selected part of your question. I'll still keep the code here in case someone needs it.

    Have you tried counting the newline separator?

    let str = "First\nSecond\nThird"
    let tok = str.componentsSeparatedByString("\n")
    print(tok.count) // Hopefully prints "3"