Swift 5: почему диапазон.Bound.utf16Offset вычисляет смещения, даже если в качестве аргумента указана пустая строка - PullRequest
3 голосов
/ 26 марта 2019

В 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
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...