I have some text on the screen:
Text(\"someText1\")
is it possible to highlight/select part of the text without creating lot Text items
Disclaimer: I was really reluctant to post my answer since I am sure that there must be a lot of way-smarter, way-better (I dunno maybe a wrapper to a UIKit view using TextKit) and more robust approaches, but... what the heck I thought it was a fun exercise and maybe someone could actually benefit from it.
So here we go:
Instead of a modifier, I'm going to make a view that holds a string (to render) and another one to hold our 'matching' text.
struct HighlightedText: View {
let text: String
let matching: String
init(_ text: String, matching: String) {
self.text = text
self.matching = matching
}
var body: some View {
let tagged = text.replacingOccurrences(of: self.matching, with: ">\(self.matching)")
let split = tagged.components(separatedBy: "")
return split.reduce(Text("")) { (a, b) -> Text in
guard !b.hasPrefix(">") else {
return a + Text(b.dropFirst()).foregroundColor(.red)
}
return a + Text(b)
}
}
}
I guess the code is quite self-explanatory but in a nutshell:
Now, we can use it with something like this:
struct ContentView: View {
@State var matching: String = "ll"
var body: some View {
VStack {
TextField("Matching term", text: self.$matching)
HighlightedText("Hello to all in this hall", matching: self.matching)
.font(.largeTitle)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
Here is a (crappy) gif demonstrating it in action:
https://imgur.com/sDpr0Ul
Finally, in case you're wondering how I'm running SwiftUI outside Xcode, here is a gist I've made for prototyping quickly in SwiftUI on the Mac