CTFrameGetLineOrigin令人难以置信的奇怪的错误

我正在使用核心文本进行文本选择。 选择机制本身正在工作,除了一件非常奇怪的事情。 我可以选择在文本视图的最后一行的罚款。 之前的所有线都捕捉到全部选定的或未选中的全部。 这里是逻辑(取自Apple的示例代码):

 NSArray *lines = (NSArray *) CTFrameGetLines(_frame);
for (int i = 0; i < [lines count]; i++) {
    CTLineRef line = (CTLineRef) [lines objectAtIndex:i];
    CFRange lineRange = CTLineGetStringRange(line);
    NSRange range = NSMakeRange(lineRange.location, lineRange.length);
    NSRange intersection = [self RangeIntersection:range withSecond:selectionRange];
    if (intersection.location != NSNotFound && intersection.length > 0) {
        // The text range for this line intersects our selection range
        CGFloat xStart = CTLineGetOffsetForStringIndex(line, intersection.location, NULL);
        CGFloat xEnd = CTLineGetOffsetForStringIndex(line, intersection.location + intersection.length, NULL);
        CGPoint origin;
        // Get coordinate and bounds information for the intersection text range
        CTFrameGetLineOrigins(_frame, CFRangeMake(i, 0), &origin);
        CGFloat ascent, descent;
        CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
        // Create a rect for the intersection and draw it with selection color
        CGRect selectionRect = CGRectMake(xStart, origin.y - descent, xEnd - xStart, ascent + descent);
        UIRectFill(selectionRect);
    }
}    

我注意到一件很奇怪的事情。 调用CTFrameGetLineOrigin似乎会破坏xStart和xEnd中的值。 我插入日志如下所示:

NSLog(@"BEFORE: xStart (%p) = %f, xEnd (%p) = %f, origin (%p) = %@", &xStart, xStart, &xEnd, xEnd, &origin, NSStringFromCGPoint(origin));
CTFrameGetLineOrigins(_frame, CFRangeMake(i, 0), &origin);
NSLog(@"AFTER: xStart (%p) = %f, xEnd (%p) = %f, origin (%p) = %@", &xStart, xStart, &xEnd, xEnd, &origin, NSStringFromCGPoint(origin));

不工作的线路输出如下

2012-09-19 12:08:39.831 SimpleTextInput [1172:11603] BEFORE:xStart(0xbfffcefc)= 18.000000,xEnd(0xbfffcef8)= 306.540009,origin(0xbfffcef0)= {0,-0}

2012-09-19 12:08:39.831 SimpleTextInput [1172:11603] AFTER:xStart(0xbfffcefc)= 370.000000,xEnd(0xbfffcef8)= 0.000000,origin(0xbfffcef0)= {0,397}

如果我执行以下操作,它会自行修复......但我不知道为什么:

CGFloat xStart = CTLineGetOffsetForStringIndex(line, intersection.location, NULL);
CGFloat xEnd = CTLineGetOffsetForStringIndex(line, intersection.location + intersection.length, NULL);
CGFloat xStart2 = 0.f; //HACK, not used at all except to pad memory
CGPoint origin;

看起来像CTFrameGetLineOrigin不尊重origin的记忆边界(记录xStart2显示它的值以同样的方式被破坏),但是如果是这种情况,那么为什么最后一行文本按预期工作? 谁可以给我解释一下这个?


CTFrameGetLineOrigins中没有奇怪的错误。

在CTFrameGetLineOrigins第二个参数中: CFRange是你想要复制的行源的范围。 如果范围的范围长度为0,则复制操作从该范围的开始索引继续到最后一个原点。

你正在通过CFRangeMake(i, 0) 。 在第一次循环迭代(i = 0)中,它将尝试用所有行起点(0到结束行)填充&原点并覆盖其他一些内存。

尝试下面的代码,这将解决问题。

NSArray *lines = (NSArray *) CTFrameGetLines(_frame);
CGPoint origins[lines.count]; //allocate enough space for buffer.
// Get all line origins...
CTFrameGetLineOrigins(_frame, CFRangeMake(0, 0), origins);

for (int i = 0; i < [lines count]; i++) {
    CTLineRef line = (CTLineRef) [lines objectAtIndex:i];
    CFRange lineRange = CTLineGetStringRange(line);
    NSRange range = NSMakeRange(lineRange.location, lineRange.length);
    NSRange intersection = [self RangeIntersection:range withSecond:selectionRange];
    if (intersection.location != NSNotFound && intersection.length > 0) {
        // The text range for this line intersects our selection range
        CGFloat xStart = CTLineGetOffsetForStringIndex(line, intersection.location, NULL);
        CGFloat xEnd = CTLineGetOffsetForStringIndex(line, intersection.location + intersection.length, NULL);
        
        CGFloat ascent, descent;
        CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
        // Create a rect for the intersection and draw it with selection color
        CGRect selectionRect = CGRectMake(xStart + origins[i].x, origins[i].y - descent, xEnd - xStart, ascent + descent);
        UIRectFill(selectionRect);
    }
}    

这看起来像是来自SimpleTextInput示例的drawRangeAsSelection 。 如果是这种情况,你可以这样做:

CTFrameGetLineOrigins(_frame, CFRangeMake(i, 1), &origin);

它将简单地检索您需要的一行的原点(这是此方法中的目标)。 我也注意到他们在: cursorRectForIndexfirstRectForNSRange犯了同样的错误。 感谢@RobNapier帮助我解决这个问题。

链接地址: http://www.djcxy.com/p/81943.html

上一篇: CTFrameGetLineOrigin unbelievably strange bug

下一篇: Emoji and CTFramesetterCreateWithAttributedString bug