I need to be able to reliably get the index of the tapped character in a Core Text frame. I have this code, which reliably gets the correct line, but which is off from zero to 2 characters on the tapped index. The error is always forward; that is, it gets the index 1 to 2 characters in advance of the correct index. Toward the beginning of a long paragraph, it is usually off by 2 characters; toward the end, it is usually correct. My text is Greek text in an attributed string, not sure if that makes a difference.
Any help would be greatly appreciated.
Thanks.
- (void)receivedTap:(UITapGestureRecognizer*)recognizer
{
CGAffineTransform transform = CGAffineTransformMake(1, 0, 0, -1, 0, self.bounds.size.height);
CGPoint point = CGPointApplyAffineTransform([recognizer locationInView:self], transform);
// Getting all CTLines
CFArrayRef lines = CTFrameGetLines(textFrame);
CFIndex countOfLines = CFArrayGetCount(lines);
int lineNumber = 0;
for ( CFIndex i = 0; i < countOfLines; i++ ) // For each CTLine
{
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CGRect lineRect = CGRectZero;
CGFloat ascent = 0, descent = 0;
// Calculating CTLine frame
CTFrameGetLineOrigins(textFrame, CFRangeMake(i, 1), &lineRect.origin);
lineRect.size.width = CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
lineRect.size.width -= CTLineGetTrailingWhitespaceWidth(line);
lineRect.size.height = ascent + descent;
lineRect.origin.y -= descent;
lineRect = CGRectIntegral(lineRect);
if ( ! CGRectContainsPoint(lineRect, point) ) {
lineNumber++;
continue;
}
NSLog(@"line is %d", lineNumber);
CFIndex touchedIndex = CTLineGetStringIndexForPosition(line, point);
NSInteger touchedIndexInt = (NSInteger)touchedIndex;
NSLog(@"found it : char %d", touchedIndexInt);
break;
}