web-dev-qa-db-fra.com

Impossible d'appeler l'initialiseur pour le type 'Range <String.Index>' avec une liste d'arguments de type '(Range <String.Index>)'

Après la mise à jour vers la version bêta de Xcode 10, qui vient apparemment avec Swift 4.1.50, l'erreur suivante s'affiche, mais je ne sais pas comment la corriger:

Impossible d'appeler l'initialiseur pour le type 'Range <String.Index>' avec une liste d'arguments de type '(Range <String.Index>)'

dans la fonction suivante en Range<Index>(start..<self.endIndex) (ligne 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
}

Une idée de comment réparer l'initialiseur?

22
LinusGeffarth

Quelques antécédents:

Dans Swift 3, des types d’intervalle supplémentaires ont été introduits, soit un total de quatre (voir par exemple Ole Begemann: Intervalles dans Swift =):

Range, ClosedRange, CountableRange, CountableClosedRange

Avec l'implémentation de SE-0143 Conformités conditionnelles dans Swift 4.2, les variantes "dénombrables" ne sont plus des types séparés, mais des alias de types (sous contrainte), par exemple

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

en conséquence, diverses conversions entre les différents types de plage ont été supprimées, telles que la

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

initialiseur de struct Range. Toutes ces modifications font partie du [stdlib] [WIP] Éliminer CountableRange (Closed) à l'aide de la conformité conditionnelle (# 13342) commit.

Donc c'est la raison pour laquelle

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

ne compile plus.

Comment réparer

Comme vous l'avez déjà compris, ceci peut être simplement résolu comme

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

ou juste

let range = start..<self.endIndex

sans l'annotation de type.

Une autre option consiste à utiliser une plage unilatérale (introduite dans Swift 4 avec SE-0172 Un sur les côtés ):

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
    }
}

Cela fonctionne car la sous-chaîne self[start...] partage ses index avec la chaîne d'origine self.

53
Martin R

Il s'avère que les plages ne doivent pas être initialisées mais peuvent simplement être créées comme suit:

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

Dans ce cas, le code serait corrigé en remplaçant Range<Index>(start..<self.endIndex) par:

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

J'ai eu le même problème, vous pouvez utiliser ce code pour résoudre le problème -

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

Référence: https://github.com/Ahmed-ALi/JSONExport/issues/121

2
Sushmita Sinha

J'ai migré de xcode 9.2 vers xcode 10.1 puis j'ai commencé à faire face à cette erreur et à le résoudre de cette manière

let range = start...end

1
Awais Nasir