В Swift 4 у меня была функция для дампа Range в выходные данные отладчика, определенные ниже:
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: "")
выбросить исключение, потому что мы пропускаем пустую строку, а сам диапазон не пустой?
ОБНОВЛЕНИЕ 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
}
}