Как определить, какое слово коснулось CoreText

Я использую CoreText для компоновки пользовательского представления. Следующим шагом для меня является определение того, какое слово нажато в событии касания/жеста. Я провел исследование по этому вопросу и нашел советы о том, как настроить URL-адрес для получения касаний, но ничего общего. Кто-нибудь знает, как это сделать?

ОБНОВИТЬ:

Вот код в моем drawRect: method self.attribString = [aString copy];

CGContextRef context = UIGraphicsGetCurrentContext();

// Flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGMutablePathRef path = CGPathCreateMutable(); //1
CGPathAddRect(path, NULL, self.bounds );

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)aString); //3
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [aString length]), path, NULL);

CTFrameDraw(frame, context); //4
UIGraphicsPushContext(context);
frameRef = frame;

CFRelease(path);
CFRelease(framesetter);

Вот где я пытаюсь обработать событие касания

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    CGContextRef context = UIGraphicsGetCurrentContext();

    CFArrayRef lines = CTFrameGetLines(frameRef);
    for(CFIndex i = 0; i < CFArrayGetCount(lines); i++)
    {
        CTLineRef line = CFArrayGetValueAtIndex(lines, i);
        CGRect lineBounds = CTLineGetImageBounds(line, context);
        NSLog(@"Line %ld (%f, %f, %f, %f)", i, lineBounds.origin.x, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height);
        NSLog(@"Point (%f, %f)", point.x, point.y);
        if(CGRectContainsPoint(lineBounds, point))
        {

Кажется, что CTLineGetImageBounds возвращает неправильное происхождение (размер кажется правильным), вот один из примеров NSLog «Строка 0 (0,562500, -0,281250, 279,837891, 17,753906)».


person xizor    schedule 11.03.2012    source источник
comment
Добавлю, что все ориджины очень похожи по стоимости.   -  person xizor    schedule 12.03.2012


Ответы (1)


В touchesEnded:withEvent: нет "текущего контекста". Вы не рисуете в этот момент. Таким образом, вы не можете осмысленно вызывать CTLineGetImageBounds().

Я считаю, что лучшим решением здесь является использование CTFrameGetLineOrigins() для поиска правильной строки (проверив начало Y), а затем использование CTLineGetStringIndexForPosition() для поиска правильного символа в строке (после вычитания начала строки из point). Это лучше всего работает для простых строк с накоплением, которые запускают все представление (например, ваше).

Другие решения:

  • Вычислить все прямоугольники линий во время drawRect: и кэшировать их. Затем вы можете просто выполнять проверки прямоугольника в touchesEnded:.... Это очень хорошее решение, если рисование менее распространено, чем постукивание. Если рисование гораздо более распространено, чем постукивание, то это плохой подход.

  • Сделайте все свои расчеты, используя CTLineGetTypographicBounds(). Это не требует графического контекста. Вы можете использовать это, чтобы разработать прямоугольники.

  • В drawRect: сгенерируйте CGLayer с текущим контекстом и сохраните его в ivar. Затем используйте контекст из CGLayer для вычисления CTLineGetImageBounds(). Контекст из CGLayer будет «совместим» с графическим контекстом, который вы используете для рисования.

Примечание: почему вы звоните UIGraphicsPushContext(context); в drawRect:? Вы устанавливаете текущий контекст в текущий контекст. Это не имеет смысла. И я не вижу соответствующего UIGraphicsPopContext().

person Rob Napier    schedule 12.03.2012
comment
Я не реализовал UIGraphicsPopContext() - я просто временно поместил туда UIGraphicsPushContext(context), чтобы попытаться получить CTLineGetImageBounds(), таким образом, когда я вызываю UIGraphicsGetCurrentContext(), я получаю последний использованный контекст. Это была всего лишь временная работа. - person xizor; 13.03.2012
comment
Я попытался добавить код в drawRect: как вы предложили, но снова я получаю исходные строки, которые очень похожи друг на друга, такие как (228,16) и (222, 22), когда эти значения не совпадают ни с чем. - person xizor; 13.03.2012
comment
Попробуйте погладить квадраты, которые вы получите (CGContextStrokeRect). Это звучит несколько разумно (не уверен, как выглядит ваше мнение). - person Rob Napier; 13.03.2012