这是一个扩展,使您可以使用Int
s而不是String.Index
值来访问子字符串的边界:
import Foundation
extension StringProtocol {
func countableRange<SearchType: StringProtocol>(
of search: SearchType,
options: String.CompareOptions = [],
range: Range<String.Index>? = nil,
locale: Locale? = nil
) -> CountableRange<Int>? {
guard let trueRange = self.range(of: search, options: options, range: range, locale: locale) else {
return nil
}
let intStart = self.distance(from: startIndex, to: trueRange.lowerBound)
let intEnd = self.distance(from: trueRange.lowerBound, to: trueRange.upperBound) + intStart
return Range(uncheckedBounds: (lower: intStart, upper: intEnd))
}
}
请注意,这可能会导致怪异,这就是Apple选择加倍努力的原因。(尽管这是一个值得商design的设计决策-通过使其变得困难来隐藏危险的东西...)
您可以从Apple的String文档中了解更多信息,但tldr的原因是这些“索引”实际上是特定于实现的。它们代表OS渲染后到字符串中的索引,因此可以根据所使用的Unicode规范版本在OS与OS之间切换。这意味着按索引访问值不再是固定时间的操作,因为必须对数据运行UTF规范才能确定字符串中的正确位置。这些索引也不会与NSString生成的值对齐(如果您将其桥接),也不会与基础UTF标量中的索引对齐。警告开发人员。