60 votes

'indice' n'est pas disponible: impossible d'indiquer une chaîne avec un objet CountableClosedRange <Int> , voir le commentaire de la documentation pour en discuter

Dans Swift 4, j'obtiens cette erreur quand j'essaie de prendre un Substring d'un String à l'aide de l'indice de la syntaxe.

'indice' est pas disponible: impossible d'indice en Chaîne de caractères avec un CountableClosedRange, voir le commentaire de documentation pour la discussion

Par exemple:

let myString: String = "foobar"
let mySubstring: Substring = myString[1..<3]

Deux questions:

  1. Comment puis-je résoudre ce problème?
  2. Où est "le commentaire de documentation pour la discussion" dont il était question dans l'erreur?

82voto

p-sun Points 1030
  1. Si vous souhaitez utiliser des indices sur des Chaînes de caractères comme "palindrome"[1..<3] et "palindrome"[1...3], l'utilisation de ces extensions.

Swift 4

extension String {
    subscript (bounds: CountableClosedRange<Int>) -> String {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return String(self[start...end])
    }

    subscript (bounds: CountableRange<Int>) -> String {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(startIndex, offsetBy: bounds.upperBound)
        return String(self[start..<end])
    }
}

Swift 3

Pour Swift 3 remplacer par return self[start...end] et return self[start..<end].

  1. Apple n'a pas l'intégrer dans le Swift de la langue, parce que la définition d'un "caractère" dépend de la façon dont la Chaîne est codé. Un personnage peut être de 8 à 64 bits, et la valeur par défaut est généralement UTF-16. Vous pouvez spécifier d'autres de la Chaîne d'encodages en String.Index.

Ceci est la documentation que Xcode erreur se réfère.

Plus sur la Chaîne de codages comme de l'UTF-8 et UTF-16

26voto

Zoff Dino Points 5010

Votre question (et d'auto-réponse) a 2 problèmes:

Subscripting une chaîne avec des Int n'a jamais été disponible dans de Swift de la Bibliothèque Standard. Ce code est non valide aussi longtemps que Swift existe:

let mySubstring: Substring = myString[1..<3]

Le nouveau String.Index(encodedOffset: ) renvoie un index en UTF-16 (16 bits) codage. Swift de la chaîne utilise Étendue de Graphème Cluster, ce qui peut prendre entre 8 et 64 bits pour stocker un caractère. Les émoticônes faire une très bonne démonstration:

let myString = "

15voto

Barry Jones Points 474
  1. Comment puis-je résoudre ce problème?

Cette erreur signifie que vous ne pouvez pas utiliser un Int dans l'indice de format, vous devez utiliser une Chaîne de caractères.Index, ce qui vous permet d'initialiser avec un encodedOffset Int.

let myString: String = "foobar"
let lowerBound = String.Index.init(encodedOffset: 1)
let upperBound = String.Index.init(encodedOffset: 3)
let mySubstring: Substring = myString[lowerBound..<upperBound]
  1. Où est "le commentaire de documentation pour la discussion" dont il était question dans l'erreur?

C'est sur GitHub dans la Norme Swift de la Bibliothèque de dépôt dans un fichier appelé UnavailableStringAPIs.swift.gyb dans le fond d'un classeur verrouillé coincé dans une ancienne lavabo avec un signe sur la porte disant: "Méfiez-vous de l'Leopard". lien

3voto

Justin Oroz Points 426

Basées sur les p-soleil est de la réponse

Swift 4

extension StringProtocol {
    subscript(bounds: CountableClosedRange<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(start, offsetBy: bounds.count)
        return self[start..<end]
    }

    subscript(bounds: CountableRange<Int>) -> SubSequence {
        let start = index(startIndex, offsetBy: bounds.lowerBound)
        let end = index(start, offsetBy: bounds.count)
        return self[start..<end]
    }
}

Changements notables:

  • Maintenant, une extension de l' StringProtocol. Cela permet aux adoptants comme Substring de aussi le gain de ces indices.
  • Fin indices sont en décalage à partir du début de l'indice des limites plutôt que le début de la chaîne. Cela empêche la traversée depuis le début de l' String deux fois. L' index méthode est O(n) où n est le décalage entre je.

2voto

Chris Frederick Points 2833

S'appuyant sur les réponses de p-sun et de Justin Oroz , voici deux extensions qui protègent contre les index non valides au-delà du début et de la fin d'une chaîne (ces extensions évitent également de ré-analyser la chaîne depuis le début, juste pour trouver l'index à la fin de la plage. ):

 extension String {

    subscript(bounds: CountableClosedRange<Int>) -> String {
        let lowerBound = max(0, bounds.lowerBound)
        guard lowerBound < self.count else { return "" }

        let upperBound = min(bounds.upperBound, self.count-1)
        guard upperBound >= 0 else { return "" }

        let i = index(startIndex, offsetBy: lowerBound)
        let j = index(i, offsetBy: upperBound-lowerBound)

        return String(self[i...j])
    }

    subscript(bounds: CountableRange<Int>) -> String {
        let lowerBound = max(0, bounds.lowerBound)
        guard lowerBound < self.count else { return "" }

        let upperBound = min(bounds.upperBound, self.count)
        guard upperBound >= 0 else { return "" }

        let i = index(startIndex, offsetBy: lowerBound)
        let j = index(i, offsetBy: upperBound-lowerBound)

        return String(self[i..<j])
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X