如何在现代Swift中通过扩展实现字符串部分内容加粗?
Swift中实现字符串部分内容加粗的扩展方案
问题中的错误分析
- NSMutableAttributedString扩展报错原因:
NSMutableAttributedString本身没有range(of:)方法,需基于其内部字符串内容查找范围,且要转换为NSRange类型才能用于富文本属性设置。 - String扩展报错原因:
String的range(of:)返回Range<String.Index>,但NSMutableAttributedString的属性设置方法需要NSRange类型,必须通过NSRange(_:in:)完成类型转换。 - Objective-C代码报错原因:OC中不存在
NSAttributedString.Key写法,应使用传统属性名常量(如NSFontAttributeName),同时OC字典的泛型声明语法错误,需改用NSString *作为键类型。
正确的Swift扩展实现
1. String扩展:生成带加粗内容的富文本
import UIKit public extension String { func attributedString(withBoldText boldText: String, boldFont: UIFont = .boldSystemFont(ofSize: 17), regularFont: UIFont = .systemFont(ofSize: 17)) -> NSAttributedString { let attributedString = NSMutableAttributedString(string: self, attributes: [.font: regularFont]) // 安全查找目标文本范围,避免强制解包崩溃 guard let range = self.range(of: boldText) else { return attributedString } let nsRange = NSRange(range, in: self) attributedString.addAttributes([.font: boldFont], range: nsRange) return attributedString } }
2. NSMutableAttributedString扩展:给已有富文本中的指定内容加粗
import UIKit extension NSMutableAttributedString { @discardableResult func bold(_ text: String, font: UIFont = .boldSystemFont(ofSize: 17)) -> Self { // 基于字符串内容查找NSRange let nsRange = self.string.range(of: text).map { NSRange($0, in: self.string) } ?? NSRange(location: NSNotFound, length: 0) guard nsRange.location != NSNotFound else { return self } self.addAttribute(.font, value: font, range: nsRange) return self } }
使用示例
String扩展用法
let originalText = "Hello world" let boldedText = originalText.attributedString(withBoldText: "world") // 直接赋值给UILabel、UITextView等控件的attributedText属性 someLabel.attributedText = boldedText
NSMutableAttributedString扩展用法
let baseAttributedString = NSMutableAttributedString(string: "Hello world", attributes: [.font: UIFont.systemFont(ofSize: 17)]) baseAttributedString.bold("world") someTextView.attributedText = baseAttributedString
额外注意事项
- 避免强制解包:如果目标文本不存在于原字符串中,强制解包会导致崩溃,必须做安全检查。
- 自定义字体:可根据需求修改
boldFont和regularFont参数,支持自定义字体。 - 匹配规则:默认的
range(of:)大小写敏感,若需忽略大小写,可使用range(of:options:)并传入.caseInsensitive选项。
内容的提问来源于stack exchange,提问作者user6631314
相关产品推荐
相关产品推荐

