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

iOS13.7中drawInRect绘制带描边NSString时换行错位问题

iOS13.7 描边文本与填充文本换行不匹配问题分析

这确实是iOS13.7的系统Bug。当设置了NSParagraphStyleAttributeName时,绘制带描边(NSStrokeWidthAttributeName)的文本和普通填充文本时,换行计算逻辑不一致,导致两者换行位置错位;而iOS14及后续版本修复了这个排版计算的问题。

问题原因

iOS13.7中,同时配置段落样式和描边属性时,文本布局引擎对换行宽度的计算存在偏差:描边文本会把描边宽度纳入换行宽度计算,填充文本仅计算字符本身宽度,最终导致两次绘制的文本换行位置不匹配。移除段落样式后,布局逻辑回退到默认处理,因此换行恢复一致。

解决方案

  • 针对iOS13.x版本单独适配:不设置段落样式,通过计算文本宽度手动调整绘制起点来实现居中效果
  • 改用一次性绘制方案:构建包含描边和填充的富文本,一次性完成绘制,避免两次绘制的布局偏差
  • 若兼容范围允许,可直接依赖iOS14+的修复,不再针对iOS13.7做特殊适配

中文注释版代码

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 绘制带描边的文本并转为图片
    UIImage *img = [[self class] drawTextWithStroke];
    // 创建图片视图并添加到当前页面
    UIImageView* imageView = [[UIImageView alloc] initWithImage:img];
    [self.view addSubview:imageView];    
}

+ (UIImage*)drawTextWithStroke
{
    // 待绘制的目标文本
    NSString* string = @"The operation couldn’t be completed. completed";

    // 定义文本绘制的矩形区域
    CGRect rect = CGRectMake(0, 0, 362, 42);
    CGSize size = CGSizeMake(rect.size.width, rect.size.height);
    // 设置字体为Arial粗体,字号18
    UIFont *font = [UIFont fontWithName:@"Arial-BoldMT" size:18];

    // 适配Retina屏幕,启用两倍分辨率绘图
   if ([UIScreen instancesRespondToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f) {
       UIGraphicsBeginImageContextWithOptions(size, NO, 2.0f);
   } else {
        UIGraphicsBeginImageContext(size);
   }

    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 创建可变字典用于存储文本样式属性
    NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];

    // 配置段落样式:设置文本居中对齐
    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    [style setAlignment: NSTextAlignmentCenter];
    attributes[ NSParagraphStyleAttributeName ] = style;
    
    // 绘制文本描边:设置字体、描边宽度为3、描边颜色为红色
    [attributes setObject:font forKey:NSFontAttributeName];
    [attributes setObject:[NSNumber numberWithFloat:3] forKey:NSStrokeWidthAttributeName];
    [attributes setObject:[UIColor redColor] forKey:NSStrokeColorAttributeName];
    [string drawInRect:rect withAttributes:attributes];

    // 绘制文本填充:移除描边相关属性,设置填充颜色为黑色
    [attributes removeObjectForKey:NSStrokeWidthAttributeName];
    [attributes removeObjectForKey:NSStrokeColorAttributeName];
    [attributes setObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName];
    [string drawInRect:rect withAttributes:attributes];
    
    // 从当前绘图上下文提取图片并返回
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 13:25:14