SwiftUI View中如何将接口返回内容的标记数字转为彩色上标
实现方案
方案1:iOS 15+ 原生SwiftUI实现(无需借助UIKit)
直接使用SwiftUI原生支持的AttributedString处理样式,无需桥接UIKit,首先修正正则匹配规则,仅匹配*包裹的数字内容:
import SwiftUI extension String { func formattedBibleContent() -> AttributedString { var attributedString = AttributedString(self) // 修正正则,仅匹配*包裹的数字节号 guard let regex = try? NSRegularExpression(pattern: "\\*(\\d+)\\*", options: []) else { return attributedString } let nsString = self as NSString let matches = regex.matches(in: self, range: NSRange(location: 0, length: nsString.length)) // 倒序遍历匹配项,避免替换后范围偏移问题 for match in matches.reversed() { let fullRange = match.range let numberRange = match.range(at: 1) let number = nsString.substring(with: numberRange) if let attributedFullRange = Range(fullRange, in: attributedString) { var numberAttr = AttributedString(number) // 设置节号样式:橙色、小字号、上标偏移 numberAttr.foregroundColor = .orange numberAttr.font = .system(size: UIFont.systemFontSize - 2) numberAttr.baselineOffset = 4 attributedString.replaceSubrange(attributedFullRange, with: numberAttr) } } return attributedString } }
调用方式直接替换原有Text的内容即可:
List { ForEach(self.viewModel.chapters) { chapter in Text(chapter.chapter_content_combined.formattedBibleContent()) } }
方案2:兼容iOS 15以下版本(借助UIKit实现)
如果需要适配更低系统版本,可以用UIViewRepresentable包装UILabel来渲染富文本:
首先定义富文本渲染组件:
struct AttributedText: UIViewRepresentable { let attributedString: NSAttributedString func makeUIView(context: Context) -> UILabel { let label = UILabel() label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping return label } func updateUIView(_ uiView: UILabel, context: Context) { uiView.attributedText = attributedString } }
编写对应的字符串处理扩展:
extension String { func formattedBibleContent() -> NSAttributedString { let attributedString = NSMutableAttributedString(string: self, attributes: [ .font: UIFont.systemFont(ofSize: UIFont.systemFontSize), .foregroundColor: UIColor.label ]) guard let regex = try? NSRegularExpression(pattern: "\\*(\\d+)\\*", options: []) else { return attributedString } let matches = regex.matches(in: self, range: NSRange(location: 0, length: self.count)) for match in matches.reversed() { let fullRange = match.range let numberRange = match.range(at: 1) let number = (self as NSString).substring(with: numberRange) let numberAttr: [NSAttributedString.Key: Any] = [ .foregroundColor: UIColor.orange, .font: UIFont.systemFont(ofSize: UIFont.systemFontSize - 2), .baselineOffset: 4 ] let attributedNumber = NSAttributedString(string: number, attributes: numberAttr) attributedString.replaceCharacters(in: fullRange, with: attributedNumber) } return attributedString } }
调用方式:
List { ForEach(self.viewModel.chapters) { chapter in AttributedText(attributedString: chapter.chapter_content_combined.formattedBibleContent()) } }
内容的提问来源于stack exchange,提问作者erikvm
相关产品推荐
相关产品推荐

