如何检测CoreText触及的单词

时间:2012-03-11 18:25:25

标签: cocoa-touch ios5 core-text

我正在使用CoreText来布局自定义视图。我的下一步是检测触摸事件/手势事件中的哪个单词被点击。我已经对此进行了研究,并建议如何自定义标记网址以接收触摸 - 但没有通用。有没有人知道如何做到这一点?

更新:

这是我的drawRect:方法中的代码     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“Line 0(0.562500,-0.281250,279.837891,17.753906)”的一个例子。

1 个答案:

答案 0 :(得分:2)

touchesEnded:withEvent:中没有“当前上下文”。你现在还没有画画。所以你不能有意义地打电话给CTLineGetImageBounds()

我认为这里最好的解决方案是使用CTFrameGetLineOrigins()找到正确的行(通过检查Y原点),然后使用CTLineGetStringIndexForPosition()在行中找到正确的字符(扣除后)来自point)的行。这适用于运行整个视图的简单堆叠线(例如您的)。

其他解决方案:

  • 计算drawRect:期间的所有直线矩形并缓存它们。然后你可以在touchesEnded:...中进行矩形检查。如果绘图不像点击那么常见,这是一个非常好的解决方案。如果绘图比点击更常见,那么这是一个糟糕的方法。

  • 使用CTLineGetTypographicBounds()完成所有计算。这不需要图形上下文。您可以使用它来计算矩形。

  • drawRect:中生成具有当前上下文的CGLayer并将其存储在ivar中。然后使用CGLayer中的上下文来计算CTLineGetImageBounds()CGLayer的上下文将与您用于绘制的图形上下文“兼容”。

旁注:您为什么在UIGraphicsPushContext(context);中拨打drawRect:?您正在将当前上下文设置为当前上下文。这没有意义。我没有看到相应的UIGraphicsPopContext()