Невозможно вызвать инициализатор для типа 'Range <String.Index> 'с аргументом списка типа' (Range <String.Index>)"

После обновления до Xcode 10 beta, которая, по-видимому, поставляется с Swift 4.1.50, я вижу следующую ошибку, которую я не уверен, как исправить:

Невозможно вызвать инициализатор для типа 'Range <String.Index>' с помощью списка аргументов типа '(Range <String.Index>)'

в следующей функции в Range<Index>(start..<self.endIndex) (строка 3):

func index(of aString: String, startingFrom position: Int? = 0) -> String.Index? {
    let start: String.Index = self.index(self.startIndex, offsetBy: position!)
    let range: Range<Index> = Range<Index>(start..<self.endIndex)
    return self.range(of: aString, options: .literal, range: range, locale: nil)?.lowerBound
}

Любая идея, как исправить инициализатор?

Ответ 1

Немного предыстории:

В Swift 3 были введены дополнительные типы диапазонов, что в сумме составило четыре (см., Например, Ole Begemann: Диапазоны в Swift 3):

Range, ClosedRange, CountableRange, CountableClosedRange

С реализацией Условных соответствий SE-0143 в Swift 4.2, "исчисляемые" варианты больше не являются отдельными типами, а являются (ограниченными) псевдонимами типа, например

 public typealias CountableRange<Bound: Strideable> = Range<Bound>
      where Bound.Stride : SignedInteger

и, как следствие, были удалены различные преобразования между различными типами диапазонов, такие как

init(_ other: Range<Range.Bound>)

инициализатор struct Range. Все эти изменения являются частью [stdlib] [WIP] Eliminate (Closed) CountableRange с использованием фиксации условного соответствия (# 13342).

Так вот почему

let range: Range<Index> = Range<Index>(start..<self.endIndex)

больше не компилируется.

Как исправить

Как вы уже поняли, это можно просто исправить как

let range: Range<Index> = start..<self.endIndex

или просто

let range = start..<self.endIndex

без аннотации типа.

Другой вариант - использовать односторонний диапазон (введен в Swift 4 с односторонними диапазонами SE-0172):

extension String {
    func index(of aString: String, startingFrom position: Int = 0) -> String.Index? {
        let start = index(startIndex, offsetBy: position)
        return self[start...].range(of: aString, options: .literal)?.lowerBound
    }
}

Это работает, потому что подстрока self[start...] делит свои индексы с исходной строкой self.

Ответ 2

Оказывается, диапазоны не нужно инициализировать, но их можно просто создать следующим образом:

let range: Range<Index> = start...end

В этом случае код будет исправлен путем замены Range<Index>(start..<self.endIndex) на:

let range: Range<Index> = start..<self.endIndex

Ответ 3

У меня была та же проблема, вы можете использовать этот код для решения проблемы -

let range = startIndex.. <characters.index(startIndex, offsetBy: 1)

Ссылка: https://github.com/Ahmed-Ali/JSONExport/issues/121

Ответ 4

Я перешел с xcode 9.2 на xcode 10.1, а затем начал сталкиваться с этой ошибкой и разрешил таким образом

let range = start...end