iOS Swift中UITableViewCell内UIButton下划线文本的国际化与内存优化问题
这个问题确实很常见——既要避免重复创建富文本对象导致的内存开销,又要保证多语言翻译的灵活性,我有几个实用的方案可以解决:
方案1:复用全局静态属性字典,动态生成本地化富文本
核心思路是把下划线、字体、颜色这些固定样式做成全局静态的属性字典,仅初始化一次;每个单元格配置时,仅用本地化字符串+复用的属性字典生成富文本。这样既避免了重复创建属性字典的内存浪费,又能通过NSLocalizedString动态获取多语言文本。
示例代码:
// 定义全局静态属性字典,仅初始化一次 private let underlineTextAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 14, weight: .medium), .foregroundColor: UIColor.systemBlue, .underlineStyle: NSUnderlineStyle.single.rawValue, .underlineColor: UIColor.systemBlue ] // 在UITableViewCell的配置方法中调用 func configure(withLocalizationKey key: String) { // 动态获取本地化字符串 let localizedText = NSLocalizedString(key, comment: "Button text for action") // 用复用的属性字典生成富文本 let attributedTitle = NSAttributedString(string: localizedText, attributes: underlineTextAttributes) yourButton.setAttributedTitle(attributedTitle, for: .normal) }
优点:实现简单,内存开销极小(属性字典全局唯一,富文本对象仅随可见单元格数量存在);完全支持多语言。
缺点:样式固定,若不同按钮需要不同下划线样式,需定义多个属性字典。
方案2:自定义UIButton子类,封装样式与多语言逻辑
把下划线文本和多语言处理逻辑封装到自定义Button子类中,这样所有需要下划线的按钮都可以复用这个类,代码更易维护,还能通过Storyboard配置部分属性。
示例代码:
import UIKit class UnderlineLocalizedButton: UIButton { // 通过IBInspectable让样式可以在Storyboard中配置 @IBInspectable var underlineColor: UIColor = .systemBlue { didSet { updateAttributedTitle() } } @IBInspectable var underlineStyle: Int = NSUnderlineStyle.single.rawValue { didSet { updateAttributedTitle() } } override func awakeFromNib() { super.awakeFromNib() updateAttributedTitle() } override func setTitle(_ title: String?, for state: UIControl.State) { // 这里传入的title应为本地化字符串的key super.setTitle(title, for: state) updateAttributedTitle() } private func updateAttributedTitle() { guard let titleKey = self.title(for: .normal) else { return } // 动态获取本地化文本 let localizedText = NSLocalizedString(titleKey, comment: "") var attributes: [NSAttributedString.Key: Any] = [ .foregroundColor: self.titleColor(for: .normal) ?? .systemBlue, .font: self.titleLabel?.font ?? UIFont.systemFont(ofSize: 14), .underlineStyle: underlineStyle, .underlineColor: underlineColor ] // 生成富文本并设置 let attributedTitle = NSAttributedString(string: localizedText, attributes: attributes) super.setAttributedTitle(attributedTitle, for: .normal) // 同步处理其他状态(如高亮、选中) super.setAttributedTitle(attributedTitle, for: .highlighted) } }
使用方式:
- 在Storyboard中把Button的类改为
UnderlineLocalizedButton - 直接在Storyboard的Title字段填写本地化字符串的key
- 可通过IB的Attributes Inspector配置下划线颜色、样式
优点:高度封装,复用性强;支持Storyboard可视化配置;自动处理多语言。
缺点:需要额外编写子类,但一次编写处处可用。
方案3:NSAttributedString分类,快速生成本地化下划线文本
如果不想自定义子类,可以给NSAttributedString写一个分类,封装“本地化key→下划线富文本”的逻辑,内部复用属性字典。
示例代码:
import UIKit extension NSAttributedString { // 静态属性字典,仅初始化一次 private static let underlineAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 14), .foregroundColor: UIColor.systemBlue, .underlineStyle: NSUnderlineStyle.single.rawValue ] static func underlineLocalizedString(withKey key: String, comment: String = "") -> NSAttributedString { let localizedText = NSLocalizedString(key, comment: comment) return NSAttributedString(string: localizedText, attributes: underlineAttributes) } // 支持自定义属性的重载方法 static func underlineLocalizedString(withKey key: String, customAttributes: [NSAttributedString.Key: Any], comment: String = "") -> NSAttributedString { let localizedText = NSLocalizedString(key, comment: comment) var combinedAttributes = underlineAttributes combinedAttributes.merge(customAttributes) { _, new in new } return NSAttributedString(string: localizedText, attributes: combinedAttributes) } }
使用方式:
// 基础用法 let attributedTitle = NSAttributedString.underlineLocalizedString(withKey: "button_action") yourButton.setAttributedTitle(attributedTitle, for: .normal) // 自定义样式 let customAttrs: [NSAttributedString.Key: Any] = [.font: UIFont.boldSystemFont(ofSize: 16)] let customAttributedTitle = NSAttributedString.underlineLocalizedString(withKey: "button_action", customAttributes: customAttrs)
优点:调用简洁,灵活性高;内存友好(属性字典静态复用)。
缺点:样式配置需要通过代码,无法在Storyboard中可视化调整。
额外优化:支持动态语言切换
如果你的App需要支持用户在运行时切换语言,还需要监听语言变化通知,刷新可见单元格:
// 在ViewController中监听通知 override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(refreshTableView), name: NSLocale.currentLocaleDidChangeNotification, object: nil) } @objc private func refreshTableView() { tableView.reloadData() } // 记得在deinit中移除通知 deinit { NotificationCenter.default.removeObserver(self) }
这样用户切换语言后,表格会重新加载,按钮的本地化文本也会自动更新。
内容的提问来源于stack exchange,提问作者TechChain
相关产品推荐
相关产品推荐

