我有一个应用程序,我使用CoreText绘制文本高亮。它运行良好,除了当我尝试使用CTLineGetStringRange
获取一行中的字符数时,它通常会给我一个比实际更大的数字。例如,在包含156个字符的行中,范围的长度为164. CTLineGetGlyphCount
返回相同的数字。
有人知道为什么会这样吗?我用来创建框架设置的NSAttributedString
使用与UITextView
完全相同的字体。
这是我的代码:
// Build the attributed string from our text data and string attribute data
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.text attributes:self.attributes];
// Create the Core Text framesetter using the attributed string
_framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedString);
// Create the Core Text frame using our current view rect bounds
UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.bounds];
_frame = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), path.CGPath, NULL);
NSArray *lines = (__bridge NSArray *) CTFrameGetLines(_frame);
for (int i = 0; i < lines.count; i++) {
CTLineRef line = (__bridge CTLineRef) [lines objectAtIndex:i];
CFRange lineRange = CTLineGetStringRange(line);
NSLog(@"lineRange: %ld, %ld", lineRange.location, lineRange.length);
CFIndex glyphCount = CTLineGetGlyphCount(line);
NSLog(@"glyphCount: %ld", glyphCount);
}
我的类是UIView
的子类,它作为子视图添加到UITextView
的子类的实例中。
修改 这是我测试的示例字符串:
textView.text = @"Marvel's The Avengers is a 2012 American superhero film produced by Marvel Studios and distributed by Walt Disney Pictures, based on the Marvel Comics superhero team of the same name.";
在这种情况下,第一行包含
“Marvel的The Avengers是由Marvel Studios制作的2012年美国超级英雄电影,由华特迪士尼影业发行,基于”长达137个字符。但它给了我一个长度为144的线的范围。
但是,当我尝试使用以下文本时,结果却不同:
textView.text = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
现在第一行包含
“Lorem ipsum dolor sit amet,consectetur adipisicing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua。Ut enim ad minim”,长度为142.但是这里它给了我正确的范围,长度为142.
然后我尝试了几个文本:
文字:
“Asgardian Loki遇到了另一个人,他是一个被称为Chitauri的外星种族的领导者。为了取回Tesseract,一个未知潜力的强大能源,另一个承诺Loki是一个Chitauri军队,他可以用来征服地球。”
结果:“Asgardian Loki遇到另一个人,一个被称为Chitauri的外星种族的领导者。以换取检索Tesseract,一个强大的”长度145.
行数范围: 145
文字:
“斯塔克和罗杰斯意识到,简单地击败他们对Loki来说是不够的;他需要公开压制他们以证明自己是地球的统治者。”
结果:“Stark和Rogers意识到简单地击败他们对Loki来说是不够的;他需要公开压制他们以证明自己是统治者”长度为146。
行数范围: 149
因此,您可以看到有时它是正确的,有时它不是。我找不到解释。
答案 0 :(得分:0)
我根据this answer中提供的提示解决了问题。
似乎因为UITextView
继承自UIScrollView
,所以每个边缘都有一个8像素的插图。这意味着我的内部UIView
有一个16像素宽的文本空间,然后是我的UITextView
,有时这种差异意味着它可以在转到新行之前再适合一个单词,这给出了错误的数字行中的字符。
因此从视图宽度中减去16个像素为我解决了这个问题。
但是,这只是我解决方案的一部分。另一部分是从核心文本中的属性字符串中删除字距调整和连字:
CFAttributedStringSetAttribute(string, textRange, kCTKernAttributeName, (__bridge CFTypeRef)([NSNumber numberWithFloat:0.0]));
CFAttributedStringSetAttribute(string, textRange, kCTLigatureAttributeName, (__bridge CFTypeRef)([NSNumber numberWithInt:0]));
现在线条非常合适。