SwiftUI中如何在Text视图显示NSMutableAttributedString并修改所有星号样式
解决方法
1. 匹配所有星号并修改样式
原代码里的range(of:)只会匹配第一个星号,要批量修改所有星号的样式,需要循环遍历查找所有匹配位置,直到找不到为止。修改后的代码如下:
func customDesc(_ text: String) -> NSMutableAttributedString { let attributedString = NSMutableAttributedString(string: text, attributes: [ .font: UIFont.systemFont(ofSize: 15, weight: .semibold) ]) let asterisk = "*" var searchRange = NSRange(location: 0, length: attributedString.length) var foundRange = (text as NSString).range(of: asterisk, options: [], range: searchRange) while foundRange.location != NSNotFound { attributedString.setAttributes([ .font: UIFont.systemFont(ofSize: 20, weight: .heavy) ], range: foundRange) // 更新搜索范围,从当前匹配位置的下一个字符开始继续查找 searchRange = NSRange(location: foundRange.location + foundRange.length, length: attributedString.length - (foundRange.location + foundRange.length)) foundRange = (text as NSString).range(of: asterisk, options: [], range: searchRange) } return attributedString }
2. 在SwiftUI中显示富文本
SwiftUI的Text视图无法直接接收NSMutableAttributedString,可以通过以下两种方式解决:
方式一:封装UIKit的UILabel(兼容iOS 13+)
创建一个UIViewRepresentable封装视图,用来承载UIKit的UILabel显示富文本:
struct AttributedText: UIViewRepresentable { let attributedString: NSAttributedString func makeUIView(context: Context) -> UILabel { let label = UILabel() label.numberOfLines = 0 // 支持多行文本 label.attributedText = attributedString return label } func updateUIView(_ uiView: UILabel, context: Context) { uiView.attributedText = attributedString } }
使用示例:
struct ContentView: View { let originalText = "The * quick * brown * fox * jumps * over * the * lazy * dog" var body: some View { AttributedText(attributedString: customDesc(originalText)) .padding() } // 这里放入前面的customDesc方法 func customDesc(_ text: String) -> NSMutableAttributedString { // ... 实现代码 } }
方式二:使用SwiftUI原生AttributedString(iOS 15+)
如果项目支持iOS 15及以上版本,直接用SwiftUI原生的AttributedString更简洁:
func customSwiftUIText(_ text: String) -> AttributedString { var attributedString = AttributedString(text) // 设置全局基础字体 attributedString.font = Font.system(size: 15, weight: .semibold) // 遍历所有星号并修改样式 for range in attributedString.ranges(of: "*") { attributedString[range].font = Font.system(size: 20, weight: .heavy) } return attributedString }
使用示例:
struct ContentView: View { let originalText = "The * quick * brown * fox * jumps * over * the * lazy * dog" var body: some View { Text(customSwiftUIText(originalText)) .padding() } func customSwiftUIText(_ text: String) -> AttributedString { // ... 实现代码 } }
内容的提问来源于stack exchange,提问作者batman
相关产品推荐
相关产品推荐

