_cpt
1
I have a code that looks like this:
enum TextHelper {
/// Searches for a first word that contains searchText inside / starts with it.
static func findWord(with searchText: String, in sentence: String) -> String? {
let searchTextNoWhitespace = searchText.trimmingCharacters(in: .whitespaces)
guard
let range = sentence.range(
of: searchTextNoWhitespace,
options: [.caseInsensitive, .diacriticInsensitive])
else { return nil }
// Not interested in words ending with searchText
guard range.upperBound != sentence.endIndex else { return nil }
guard !sentence[range.upperBound].isWhitespace else { return nil }
return findWord(around: range.upperBound, in: sentence)
}
static func findWord(around index: String.Index, in text: String) -> String? {
var start = index
// We start from match index, and go left looking for whitespace
while start > text.startIndex && !text[start].isWhitespace {
start = text.index(before: start)
}
// Previous while loop stops when it sees whitespace, so start index will point before the symbol that we need.
if start != text.startIndex {
start = text.index(after: start)
}
var end = index
// Start from last match index, and look till the next whitespace or end of the string.
while end < text.endIndex && !text[end].isWhitespace {
end = text.index(after: end)
}
return String(text[start..<end])
}
}
And it crashes for some users on start = text.index(before: start) with Swift/StringCharacterView.swift:98: Fatal error: String index is out of bounds. I am expecting the body of the while loop not to be executed if start <= text.startIndex, so a call to index(before:) should be valid. Is it possible that range returned by range(of: options:) is "misaligned" (because of diacritics/etc), and when used as a param to index(before) it triggers this assert?
index(before:) | Apple Developer Documentation says:
i
A valid index of the collection. i must be greater than startIndex.
Is it possible that your range starts at the very beginning of the string, and i = startIndex, and thus there is no characters before i (before startIndex)?