You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Core Text绘制NSAttributedString时文本重复显示的原因排查

问题分析与解决

你遇到的文本重复问题,核心原因是每次调用drawGlyphsForGlyphRange:时,都绘制了整个NSAttributedString内容,而非当前方法指定的glyph范围对应的文本片段。同时代码存在变量名错误(使用了未定义的glyphRange,实际参数为glyphsToShow)。

解决步骤

  1. 修正变量名:将代码中所有glyphRange替换为方法传入的glyphsToShow。
  2. 限定绘制范围:把glyph范围转换为对应的字符范围,仅绘制当前需要的文本片段,而非整个字符串。
  3. 规范属性调用:使用self.textStorage替代直接引用storage,保证属性访问的正确性。

修改后的代码

- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin {
    NSTextContainer *textContainer = [self textContainerForGlyphAtIndex:glyphsToShow.location effectiveRange:nil];
    CGRect someRect = [self boundingRectForGlyphRange:glyphsToShow inTextContainer:textContainer];

    CGFloat xPoint = someRect.origin.x + origin.x;
    CGFloat width = 330;
    CGFloat calculatedHeight = 310;
    CGRect adjustedRect = CGRectMake(xPoint, someRect.origin.y + origin.y, width, calculatedHeight);

    // 将glyph范围转换为对应的字符范围
    NSRange characterRange = [self characterRangeForGlyphRange:glyphsToShow actualGlyphRange:nil];
    
    // 创建Core Text框架,仅绘制当前需要的字符范围
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)self.textStorage);
    CGPathRef path = CGPathCreateWithRect(adjustedRect, NULL);
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(characterRange.location, characterRange.length), path, NULL);

    // 翻转坐标系(需要时取消注释)
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    // CGContextTranslateCTM(context, 0, adjustedRect.size.height + adjustedRect.origin.y * 2);
    // CGContextScaleCTM(context, 1.0, -1.0);

    // 绘制指定范围的文本
    CTFrameDraw(frame, context);

    // 清理Core Text资源
    CFRelease(frame);
    CGPathRelease(path);
    CFRelease(frameSetter);
}

额外注意事项

  • 不要调用super,否则系统默认绘制逻辑会与你的Core Text绘制叠加,再次导致文本重复。
  • 若后续需要解决文本倒置问题,取消注释坐标翻转的代码即可。

内容的提问来源于stack exchange,提问作者SirRupertIII

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:18:24