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