I am trying to create a function where a multi-line string is spell checked and a single SwiftUI Text() view is returned with any misspelled words highlighted in red.
I have almost cracked it by splitting the string by newlines, then splitting the lines by whitespace and then checking each word.
My main issue is that I am getting an extra new line added at the end of the resulting Text view. Is there anyway I can trim the last Text("\n")
or prevent it from being added to the last line?
Also, if there is any way to make it more efficient as there is a slight lag introduced as a lot of text in an array gets checked and so the function is called many times?
Many thanks in advance
func formatText(multiLineText: String) -> Text {
let lineArray = multiLineText.components(separatedBy: .newlines)
let stringToTextView = lineArray.reduce(Text(""), {
return $0 formatLineText(singleLineText: $1) Text("\n")
})
return stringToTextView
}
func formatLineText(singleLineText: String) -> Text {
let stringArray = singleLineText.components(separatedBy: .whitespaces)
let stringToTextView = stringArray.reduce(Text(""), {
if !wordIsValid(word: $1) {
return $0 Text($1).foregroundColor(Color.red).underline() Text(" ")
}
else {
return $0 Text($1) Text(" ")
}
})
return stringToTextView
}
func wordIsValid(word: String) -> Bool {
let checker = UITextChecker()
let range = NSRange(location: 0, length: word.utf16.count)
let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en_GB")
return misspelledRange.location == NSNotFound
}
CodePudding user response:
You could use .enumerated
in your reduce
to check to see if the item is the last one or not -- if it is, don't return the \n
.
func formatText(multiLineText: String) -> Text {
let lineArray = multiLineText.components(separatedBy: .newlines)
let stringToTextView = lineArray.enumerated().reduce(Text(""), { (acc,item) in
return acc formatLineText(singleLineText: item.1) Text(item.0 != lineArray.endIndex - 1 ? "\n" : "")
})
return stringToTextView
}
In terms of performance, I'd move the let checker = UITextChecker()
to somewhere where it doesn't get recreated on every single call to wordIsValid