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

iOS 16中CIAttributedTextImageGenerator多行文本生成过宽问题

iOS 16下CIAttributedTextImageGenerator多行文本宽度异常问题解决

问题重现

使用CIAttributedTextImageGenerator生成多行文本对应的CIImage时,iOS 16及以上版本出现宽度异常膨胀问题:每增加一行文本,图片宽度会大幅增长,最终生成的图片宽高比与实际文本排版严重不符(实际文本高度远大于宽度,但图片宽度反而超过高度);单行文本生成正常,iOS 15及以前版本无此问题。

用户核心实现代码:

let attributes: [NSAttributedString.Key: Any] = [
    .font: font,
    .foregroundColor: textColor,
    .backgroundColor: textBackgroundColor,
    .shadow: shadow,
    .strokeColor: strokeColor,
    .strokeWidth: strokeWidth
]

let attributedQuote = NSAttributedString(string: text, attributes: attributes)

let textGenerationFilter = CIFilter(name: "CIAttributedTextImageGenerator")!
textGenerationFilter.setValue(attributedQuote, forKey: "inputText")
if #available(iOS 16.0, macCatalyst 16.0, macOS 13.0, tvOS 16.0, *) {
    textGenerationFilter.setValue(CGFloat(0), forKey: "inputPadding")
}
textGenerationFilter.setValue(NSNumber(value: Double(4.0)), forKey: "inputScaleFactor")

guard let textImage = textGenerationFilter.outputImage else {
    return nil
}

问题原因

iOS 16中CIAttributedTextImageGenerator的多行文本排版计算逻辑发生变更:当未明确约束文本宽度时,滤镜错误地将每行文本的潜在最大宽度叠加,导致整体宽度无限制膨胀。而iOS 15及以前版本会自动基于文本换行后的实际最大宽度确定图片宽度。

解决方案

给NSAttributedString添加.paragraphStyle属性,通过设置preferredMaxLayoutWidth明确文本的最大宽度约束,让滤镜能正确计算多行文本的实际排版宽度。

修改步骤

  1. 创建并配置NSMutableParagraphStyle:
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byWordWrapping // 根据需求选择换行模式,如.byCharWrapping
// 关键:设置文本的最大宽度约束
paragraphStyle.preferredMaxLayoutWidth = desiredMaxWidth // 替换为你期望的最大宽度,比如控件宽度或固定值
  1. 将paragraphStyle加入属性字典:
let attributes: [NSAttributedString.Key: Any] = [
    .font: font,
    .foregroundColor: textColor,
    .backgroundColor: textBackgroundColor,
    .shadow: shadow,
    .strokeColor: strokeColor,
    .strokeWidth: strokeWidth,
    .paragraphStyle: paragraphStyle // 添加此行
]

动态计算最大宽度(可选)

如果无法提前确定desiredMaxWidth,可先计算文本在当前属性下的实际排版宽度,再将其设为preferredMaxLayoutWidth:

// 先创建不带paragraphStyle的临时富文本
let tempAttributedText = NSAttributedString(string: text, attributes: [
    .font: font,
    .foregroundColor: textColor,
    .backgroundColor: textBackgroundColor,
    .shadow: shadow,
    .strokeColor: strokeColor,
    .strokeWidth: strokeWidth
])
// 计算文本实际排版的宽高
let tempSize = CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)
let textRect = tempAttributedText.boundingRect(with: tempSize, options: [.usesLineFragmentOrigin], context: nil)
// 配置paragraphStyle
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byWordWrapping
paragraphStyle.preferredMaxLayoutWidth = textRect.width
// 最终创建带约束的富文本
let attributedQuote = NSAttributedString(string: text, attributes: [
    .font: font,
    .foregroundColor: textColor,
    .backgroundColor: textBackgroundColor,
    .shadow: shadow,
    .strokeColor: strokeColor,
    .strokeWidth: strokeWidth,
    .paragraphStyle: paragraphStyle
])

修改后,CIAttributedTextImageGenerator会按照指定的最大宽度排版多行文本,生成的图片宽度将与文本实际排版宽度匹配,不会再出现异常膨胀。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:46:16