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

标签 objective-c ios core-text

我正在使用核心文本进行文本选择。选择机制本身是有效的,除了一件非常奇怪的事情。我可以在 TextView 的最后一行选择好。所有先前的行都捕捉到全部选中或根本未选中。这是逻辑(取自 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 到结束行)填充 &origin 并覆盖一些其他内存。

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

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);
    }
}    

关于objective-c - CTFrameGetLineOrigin 令人难以置信的奇怪错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12488106/

相关文章:

ios - 无法在 cocos2d-x v3 上进行多点触控

cocoa-touch - iOS 上的 NSAttributedString 和链接

ios - AVAudioRecorder 丢失最后几秒

objective-c - 我们如何设置或获取任何控件的焦点 - 并将焦点留在 Cocoa 中

iphone - 从 block 中返回整数

objective-c - 使用 ARC 进行指针转换

ios - 在 xcode 7 ios9 中未触发展开 segue Action

ios - 在 CoreText 中将半行向左对齐,第二行向右对齐

objective-c - 通过 CTFontRef 或 CGFontRef 对象中的字形索引获取 unicode 字符

iphone - CALayer 与 drawInRect : performance?