Introduction : Le "piège" qui attend chaque développeur Swift
\n\nImagine la situation : tu écris du code en Swift en toute confiance, tout se passe bien, et soudain tu dois prendre les trois premiers caractères d'une chaîne. Sans réfléchir, tu écris quelque chose comme myString[0..<3] — et tu obtiens... une erreur de compilation. Ça te dit quelque chose ?
Bienvenue dans le monde de String substring en Swift. C'est l'un de ces sujets qui cause une vraie douleur chez les débutants et même chez les développeurs expérimentés venant d'autres langages. La question "How does String substring work in Swift" sur Stack Overflow a rassemblé des milliers de vues — et ce n'est pas un hasard.
\n\nDans cet article, nous allons voir pourquoi Swift est si "étrange" quand il s'agit de travailler avec des sous-chaînes, comment utiliser correctement substring en Swift, et quelles nouvelles fonctionnalités sont apparues dans les dernières versions. C'est parti !
\n\nPourquoi Swift ne permet-il pas simplement de découper un morceau de chaîne ?
\n\nDans la plupart des langages (Python, JavaScript, C#), une chaîne est simplement un tableau de caractères. Tu veux une sous-chaîne ? Tu écris str[0:3] et tu obtiens le résultat. En Swift, c'est différent.
La raison réside dans la gestion d'Unicode. Les chaînes en Swift ne sont pas simplement des octets ou des caractères ASCII. Elles sont composées de grapheme clusters. Un seul caractère visible par l'utilisateur (par exemple "é" ou "👍🏽") peut occuper plusieurs Character ou même plusieurs Unicode.Scalar. Imagine que tu coupes une chaîne au milieu d'un tel cluster — tu obtiendrais des données corrompues.
C'est pourquoi Swift utilise des index (String.Index), et non des nombres entiers. Cela garantit que tu ne couperas jamais un caractère en deux.
Les bases : String.Index et extraction simple d'une sous-chaîne
\n\nCommençons par un exemple de base. Supposons que nous ayons une chaîne :
\n\nlet fullString = "Bonjour, Swift !"\n// Nous voulons prendre le mot "Swift"\nlet startIndex = fullString.index(fullString.startIndex, offsetBy: 9)\nlet endIndex = fullString.index(fullString.startIndex, offsetBy: 14)\nlet substring = fullString[startIndex..<endIndex]\nprint(substring) // Affiche : "Swift"\n\nRemarque : substring est de type Substring, et non String. C'est une différence importante. Substring est une "fenêtre" sur la chaîne d'origine. Elle ne copie pas les données, mais fait simplement référence à une partie de la mémoire de la chaîne d'origine. C'est super efficace, mais cela peut entraîner des fuites mémoire si la chaîne d'origine est grande et la sous-chaîne petite.
Pour transformer un Substring en une String complète, utilise simplement l'initialiseur :
let newString = String(substring)\nprint(newString) // "Swift"\n\nSucre syntaxique : RangeExpression
\n\nÉcrire index(offsetBy:) à chaque fois est fastidieux. Heureusement, Swift permet d'utiliser des formes plus courtes avec RangeExpression.
Opérateur ... (ClosedRange)
\nlet str = "Hello, World!"\nif let range = str.range(of: "World") {\n let worldSubstring = str[range]\n print(worldSubstring) // "World"\n}\n\nIntervalles partiels (Partial Range)
\nTu veux prendre tout jusqu'à un certain index ou après ? Facile :
\nlet text = "Swift Programming"\nlet prefix = text[..<text.index(text.startIndex, offsetBy: 5)]\nprint(prefix) // "Swift"\n\nlet suffix = text[text.index(text.startIndex, offsetBy: 6)...]\nprint(suffix) // "Programming"\n\nRemarque : prefix et suffix sont aussi des Substring.
Méthodes intégrées : prefix, suffix, dropFirst, dropLast
\n\nSwift fournit des méthodes pratiques qui évitent de calculer manuellement les index. Elles retournent un Substring.
- \n
str.prefix(5)— les 5 premiers caractères. \n str.suffix(3)— les 3 derniers caractères.