You would need to first create a regex to find some digits separated by the ^
character (\d+)(\^)(\d+)
. Then you would need to get the fourth range of the first match and change its baseline offset. Then get the third range delete its character:
import SwiftUI
struct ContentView: View {
@ObservedObject private var bindingManager = TextBindingManager(string: "The universe has 10^12 bla bla bla")
var body: some View {
VStack(alignment: .leading) {
AttributedLabel(attributedString: bindingManager.attributedString)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct AttributedLabel: UIViewRepresentable {
let attributedString: NSAttributedString
func makeUIView(context: UIViewRepresentableContext<Self>) -> UILabel {
let label = UILabel()
DispatchQueue.main.async { label.attributedText = attributedString }
return label
}
func updateUIView(_ uiView: UILabel, context: Context) {
DispatchQueue.main.async { uiView.attributedText = attributedString }
}
}
class TextBindingManager: ObservableObject {
@Published var string: String
var attributedString: NSAttributedString {
let mutableAttributedString = NSMutableAttributedString(string: string)
if let matches = try! NSRegularExpression(pattern: #"(\d+)(\^)(\d+)"#)
.matches(in: string,
range: .init(string.startIndex...,
in: string)).first {
if matches.numberOfRanges == 4 {
mutableAttributedString.setAttributes([.font: UIFont.systemFont(ofSize: 10),.baselineOffset: 10],
range: matches.range(at: 3))
mutableAttributedString.deleteCharacters(in: matches.range(at: 2))
}
}
return mutableAttributedString
}
init(string: String) { self.string = string }
}
