#swift
#swift
Вопрос:
В Swift 4 у меня была функция для сброса диапазона в выходные данные отладчика, определенные следующим образом:
extension Range where Bound == String.Index {
public func dump() -> String {
return "[(lowerBound.encodedOffset)..<(upperBound.encodedOffset)] ((length))"
}
public var length: Int {
return upperBound.encodedOffset - lowerBound.encodedOffset
}
}
Поскольку в Swift 5 encodedOffset
не рекомендуется, я изменил реализацию, как показано ниже:
extension Range where Bound == String.Index {
public func dump(string: String) -> String {
let lower = lowerBound.utf16Offset(in: string)
let upper = upperBound.utf16Offset(in: string)
let result = "[(lower)..<(upper)] ((upper - lower))"
return result
}
}
Тест работает должным образом после обновления реализации:
class RangeTests: LogicTestCase {
func test_dump() {
let string = "Hello!"
let range = string.range(of: "ello")
Assert.equals(range?.dump(string: string), "[1..<5] (4)")
}
}
Но функция dump
работает корректно, даже если передается пустая строка:
class RangeTests: LogicTestCase {
func test_dump() {
let string = "Hello!"
let range = string.range(of: "ello")
Assert.equals(range?.dump(string: ""), "[1..<5] (4)")
}
}
Не следует, например, вызывать lowerBound.utf16Offset(in: "")
исключение throw, потому что мы передаем пустую строку, в то время как сам диапазон не пуст?
ОБНОВЛЕНИЕ 1:
С помощью трюка, lowerBound.utf16Offset(in: "")
упомянутого выше, следующие две версии функции сдвига индекса образца работают идентично:
extension String.Index {
// Deprecated due `encodedOffset`
public func shifting(by offset: Int) -> String.Index {
return String.Index(encodedOffset: encodedOffset offset)
}
// Possible Swift 5 replacement to achieve index manipulation
// without reference to string.
public func shifting(by offset: Int) -> String.Index {
let newOffset = utf16Offset(in: "") offset
let referenceString = String(repeating: " ", count: newOffset)
let result = String.Index(utf16Offset: newOffset, in: referenceString)
return result
}
}
Комментарии:
1. Не используйте кодированное смещение, используйте метод string distance. Попробуйте
"😀😀😀".lastIndex(of: "😀")?.encodedOffset
, чтобы вернуть 42. почему вы не используете свойство range
count
?3.
range.count
причина ошибкиType 'String.Index' does not conform to protocol 'Strideable'
: 04. моя ошибка. Для вычисления расстояния вам нужен экземпляр строки
5.
let string = "😀😀😀" let range = string.startIndex..<string.endIndex let distance = string.distance(from: range.lowerBound, to: range.upperBound) print(distance) // 3