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

iOS 15中如何让本地化字符串指定部分文本显示为粗体?

问题

在SwiftUI视图里展示文本时,想让部分文本用不同字体。我的Localizable文件里有这么个本地化字符串:

"unencrypted_emails_header" = "we may send you **business email unencrypted** and that you assume the risks"

目标是让**包裹的内容显示为粗体。

最开始试了这段代码:

Text(headerText())
     .rchFont(.rchBody)

private func headerText() -> String {
    let rchBodyFont = RCHFont.rchBody
    let rchBodyBoldFont = RCHFont.rchBodyBold
    let headerString = strings.unencryptedEmailsHeader.replacingOccurrences(of: "**", with: "")
    let attributedString = NSMutableAttributedString(string: headerString)
    if let range = headerString.range(of: #"(?<=\*\*)(.*?)(?=\*\*)"#, options: .regularExpression) {
        let nsRange = NSRange(range, in: headerString)
        attributedString.addAttribute(.font, value: rchBodyBoldFont, range: nsRange)
    }
    return attributedString.string
}

结果是**确实被移除了,但对应文本并没有变成粗体。项目最低支持iOS 15。

后来又改了写法:

Text(LocalizedStringKey(strings.unencryptedEmailsHeader))
        .rchFont(.rchBody)

不加.rchFont(.rchBody)的时候粗体是生效的,但一加这个自定义字体修饰符,粗体就被覆盖了,显示不出来。

解决方案

方法一:用AttributedString解析Markdown并适配自定义字体

iOS 15已经支持AttributedString的Markdown解析,我们可以先把本地化字符串转成带样式的AttributedString,再给不同样式的文本段分配对应的自定义字体:

// 视图中直接使用
Text(try! AttributedString(markdown: strings.unencryptedEmailsHeader)
    .applyCustomFonts(body: RCHFont.rchBody, boldBody: RCHFont.rchBodyBold))

然后给AttributedString加个扩展方法来处理字体替换:

extension AttributedString {
    func applyCustomFonts(body: UIFont, boldBody: UIFont) -> AttributedString {
        var mutableString = self
        // 遍历每个文本片段,根据粗体属性分配对应字体
        for run in mutableString.runs {
            if run.fontProperties?.weight == .bold {
                mutableString[run.range].font = boldBody
            } else {
                mutableString[run.range].font = body
            }
        }
        return mutableString
    }
}

这个思路是先通过Markdown解析保留粗体标记,再把默认的粗体/常规字体替换成你自定义的字体,既保留了样式,又用上了自定义字体。

方法二:修改自定义字体修饰符的实现

如果你的.rchFont是自己写的ViewModifier,可以调整它的逻辑,让它尊重文本原有的粗体权重:

extension View {
    func rchFont(_ style: RCHFont) -> some View {
        self.modifier(RCHFontModifier(style: style))
    }
}

struct RCHFontModifier: ViewModifier {
    let style: RCHFont
    
    func body(content: Content) -> some View {
        content
            // 这里不要直接覆盖整个字体,而是结合原有权重处理
            .font(Font(style.font))
            .fontWeight(style == .rchBodyBold ? .bold : .regular)
    }
}

不过这种方式只适合简单场景,如果文本是通过LocalizedStringKey生成的多样式文本,还是方法一的AttributedString处理更准确。

方法三:拆分文本组合(仅适合固定结构的文本)

如果你的本地化字符串结构不会随语言变化,可以直接拆分文本分别设置字体再组合:

Text(strings.unencryptedEmailsPrefix)
    .font(Font(RCHFont.rchBody))
+ Text(strings.unencryptedEmailsBoldPart)
    .font(Font(RCHFont.rchBodyBold))
+ Text(strings.unencryptedEmailsSuffix)
    .font(Font(RCHFont.rchBody))

但这种方式不推荐用于本地化场景,因为不同语言的语序可能完全不同,拆分后容易出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:54:52