0

I am reading lines from a text files and displaying those lines on a Text element.

I may have scientific notation elements in there like

10^12 
10^9

etc...

I need to display that as

10^2

10^9

and these numbers are in the middle of phrases, like..

The universe has 10^12 bla bla bla

How can I do that?

I show no code because I am clueless on that one.

Thanks

Ronnie
  • 332
  • 2
  • 11
  • 5
    Does this answer your question https://stackoverflow.com/a/60232789/12299030? (of course you need to parse string at first to find needed pattern and then join back Text components). – Asperi Nov 28 '20 at 18:31

3 Answers3

3

This kind of things are much easier in SwiftUI, there is lots of ways for this job in SwiftUI one of them could be this down code:

enter image description here

struct ContentView: View {

@State var yourFirstText: String = "The universe has "

@State var yourLastText: String = " bla bla bla"

var body: some View {

    Text(yourFirstText) + Text("10") + Text("12").font(Font.footnote).baselineOffset(6.0) + Text(yourLastText)


    }
}
ios coder
  • 1
  • 4
  • 31
  • 91
2

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 }
}

enter image description here

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
1

Alternative Solution using NSAttributedString

Instead of using multiple Text compoments you could use just a single one and compose the text itself with NSAttributedString

let font: UIFont = .systemFont(ofSize: 17)
let text = NSMutableAttributedString(
    string:"1012", attributes: [.font : font]
)
text.setAttributes(
    [.baselineOffset: 10, .font : font.withSize(10)],
    range: NSRange(location: 2, length: 2)
)

and then simply assign attributedString to your UILabel

yourLabel.attributedText = text

Since this answer does not apply to SwiftUI Text component directly, check out this answer to learn how to use UIKit UILabel inside your SwiftUI views.

Witek Bobrowski
  • 3,749
  • 1
  • 20
  • 34
  • @Ronnie: depending on choosing platform of coding make multiple answer possible like this one for UIKit, but the Future belongs to SwiftUI, if you want invest your time, just start with SwiftUI. – ios coder Nov 28 '20 at 19:19
  • 1
    Let's not make it SwiftUI vs UIKit because both are great technologies and arguing which one is better is counterproductive. I am just supplying an alternative solution the first answer posted, not only of the OP but for anyone who finds this questions in the future. – Witek Bobrowski Nov 28 '20 at 19:24
  • 1
    @ witek: I am 100% agree with you and it is very nice we could find answers in SwiftUI and UIKit! good job! – ios coder Nov 28 '20 at 19:27