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

Swift中根据通知单元格类型生成富文本字符串的实现方案

解决方案:本地化模板+富文本标记实现多语言适配的通知标题样式

核心思路

放弃拆分单词的低效方式,改用本地化字符串模板+自定义标记结合枚举关联数据的方案,同时用结构体封装不同通知类型的动态参数,既解决多语言词序适配问题,又能灵活控制高亮样式。

步骤1:重构枚举与参数结构体

将原枚举的关联值从单一图片扩展为包含所有动态数据的结构体,让每种通知类型的所需参数更清晰:

// 封装各通知类型的动态参数
struct NotificationContent {
    struct EventDue {
        let eventName: String
        let dueTime: String
        let image: UIImage
    }
    struct EventCreated {
        let eventName: String
        let image: UIImage
    }
    struct EventChanged {
        let eventName: String
        let changeDesc: String
        let image: UIImage
    }
    struct InviteDeclined {
        let userName: String
        let eventName: String
        let image: UIImage
    }
    struct AdminMessage {
        let messageTitle: String
        let avatar: UIImage
    }
    struct Invite {
        let inviterName: String
        let eventName: String
        let avatar: UIImage
    }
}

// 重构后的枚举,关联对应参数结构体
enum NotificationType {
    case eventDue(NotificationContent.EventDue)
    case eventCreated(NotificationContent.EventCreated)
    case eventChanged(NotificationContent.EventChanged)
    case inviteDeclined(NotificationContent.InviteDeclined)
    case adminMessage(NotificationContent.AdminMessage)
    case invite(NotificationContent.Invite)
    
    var image: UIImage? {
        switch self {
        case .eventDue(let content): return content.image
        case .eventCreated(let content): return content.image
        case .eventChanged(let content): return content.image
        case .inviteDeclined(let content): return content.image
        case .adminMessage(let content): return content.avatar
        case .invite(let content): return content.avatar
        }
    }
}

步骤2:添加多语言本地化模板

在Localizable.strings中为每种通知类型定义带标记的模板,用*标记需要高亮的部分,同时适配不同语言的词序:

// 中文模板
"notification.event_due" = "您的 *%@* 将于 *%@* 开始";
"notification.event_created" = "已创建活动 *%@*";
"notification.event_changed" = "活动 *%@* 已更新:*%@*";
"notification.invite_declined" = "*%@* 拒绝了您的 *%@* 邀请";
"notification.admin_message" = "管理员通知:*%@*";
"notification.invite" = "*%@* 邀请您参加 *%@*";

// 德语模板(适配词序)
"notification.event_due" = "Ihre *%@* beginnt um *%@*";

步骤3:ViewModel中生成富文本标题

在NotificationViewModel中,根据枚举类型匹配模板、替换参数,再解析标记生成带样式的富文本:

class NotificationViewModel {
    private let notificationType: NotificationType
    private let defaultTextColor = UIColor.gray
    private let highlightTextColor = UIColor.black
    private let font = UIFont.systemFont(ofSize: 16)
    
    init(type: NotificationType) {
        self.notificationType = type
    }
    
    var formattedTitle: NSAttributedString {
        let templateString: String
        let arguments: [CVarArg]
        
        // 匹配对应模板与参数
        switch notificationType {
        case .eventDue(let content):
            templateString = NSLocalizedString("notification.event_due", comment: "")
            arguments = [content.eventName, content.dueTime]
        case .eventCreated(let content):
            templateString = NSLocalizedString("notification.event_created", comment: "")
            arguments = [content.eventName]
        case .eventChanged(let content):
            templateString = NSLocalizedString("notification.event_changed", comment: "")
            arguments = [content.eventName, content.changeDesc]
        case .inviteDeclined(let content):
            templateString = NSLocalizedString("notification.invite_declined", comment: "")
            arguments = [content.userName, content.eventName]
        case .adminMessage(let content):
            templateString = NSLocalizedString("notification.admin_message", comment: "")
            arguments = [content.messageTitle]
        case .invite(let content):
            templateString = NSLocalizedString("notification.invite", comment: "")
            arguments = [content.inviterName, content.eventName]
        }
        
        // 替换占位符得到原始字符串
        let rawString = String(format: templateString, arguments: arguments)
        // 解析标记生成富文本
        return parseHighlightedString(rawString)
    }
    
    private func parseHighlightedString(_ string: String) -> NSAttributedString {
        let attributedString = NSMutableAttributedString(string: string, attributes: [
            .foregroundColor: defaultTextColor,
            .font: font
        ])
        
        var range = string.startIndex..<string.endIndex
        while let startRange = string.range(of: "*", range: range) {
            let startPos = string.distance(from: string.startIndex, to: startRange.lowerBound)
            attributedString.deleteCharacters(in: NSRange(startPos..<startPos+1))
            
            guard let endRange = string.range(of: "*", range: startRange.upperBound..<string.endIndex) else { break }
            let endPos = string.distance(from: string.startIndex, to: endRange.lowerBound) - 1
            
            // 设置高亮样式
            let highlightRange = NSRange(startPos..<endPos)
            attributedString.addAttributes([
                .foregroundColor: highlightTextColor
            ], range: highlightRange)
            
            attributedString.deleteCharacters(in: NSRange(endPos..<endPos+1))
            range = endRange.upperBound..<string.endIndex
        }
        
        return attributedString
    }
}

方案优势

  • 多语言兼容:本地化模板可自由调整词序,不受固定拆分逻辑限制
  • 扩展性强:新增通知类型只需补充结构体、模板和枚举分支
  • 样式灵活:通过标记可任意控制高亮范围,支持复杂文本样式组合

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:30:35