Swift - Fractionner la chaîne sur plusieurs lignes

Réponses:

444

Swift 4 inclut la prise en charge des littéraux de chaîne multi-lignes . En plus des sauts de ligne, ils peuvent également contenir des citations non échappées.

var text = """
    This is some text
    over multiple lines
    """

Les versions plus anciennes de Swift ne vous permettent pas d'avoir un seul littéral sur plusieurs lignes mais vous pouvez ajouter des littéraux ensemble sur plusieurs lignes:

var text = "This is some text\n"
         + "over multiple lines\n"
Connor
la source
2
Le problème avec cette approche est que vous pouvez facilement atteindre trop de lignes «continues» dans Swift (à partir de Xcode 6.2 beta), où il se plaint que l'expression est «trop complexe pour être résolue dans un délai raisonnable» et pour envisager de rompre vers le bas à des expressions plus simples. C'est moche mais assez facile à accomplir, il suffit d'envelopper les sections dans des parens.
clearlight
8
N'oubliez pas d'ajouter un espace entre la citation de fermeture et le +, sinon vous obtiendrez une erreur "'+' n'est pas un opérateur unaire postfix"
Orlin Georgiev
Cela fonctionne toujours, mais vous devez ajouter manuellement le \npersonnage. Par exemple, dans le REPL: println("foo\n" + "bar")imprime fooet barsur des lignes distinctes.
Brian Gerstle
Il devrait être corrigé dans Xcode 7 "La concaténation des littéraux de chaîne Swift, y compris sur plusieurs lignes, est une optimisation garantie au moment de la compilation, même sur -Onone.," Adcdownload.apple.com/WWDC_2015/Xcode_7_beta/…
Kostiantyn Koval
2
Ne fonctionne pas pour les valeurs de casse enum qui utilisent des chaînes :(
Lars Blumberg
32

J'ai utilisé une extension sur String pour obtenir des chaînes multilignes tout en évitant le bug de blocage du compilateur. Il vous permet également de spécifier un séparateur afin que vous puissiez l'utiliser un peu comme la fonction de jointure de Python

extension String {
    init(sep:String, _ lines:String...){
        self = ""
        for (idx, item) in lines.enumerated() {
            self += "\(item)"
            if idx < lines.count-1 {
                self += sep
            }
        }
    }

    init(_ lines:String...){
        self = ""
        for (idx, item) in lines.enumerated() {
            self += "\(item)"
            if idx < lines.count-1 {
                self += "\n"
            }
        }
    }
}



print(
    String(
        "Hello",
        "World!"
    )
)
"Hello
World!"

print(
    String(sep:", ",
        "Hello",
        "World!"
    )
)
"Hello, World!"
mcornell
la source
1
Ces méthodes sont parfaites. Même dans la dernière version de Swift 1.2, les longs littéraux se compilent très lentement, et ces méthodes évitent cette surcharge.
phatmann
2
Pour tous ceux qui utilisent Swift 2, enumerate(lines)est maintenantlines.enumerate()
Jedidja
2
@mcornell C'est bien, mais ne fait pas joinWithSeparatoressentiellement la même chose? ["Hello", "World!"].joinWithSeparator(", ")
Dan Loewenherz
27

Ce fut la première chose décevante à propos de Swift que j'ai remarquée. Presque tous les langages de script permettent des chaînes multi-lignes.

C ++ 11 a ajouté des littéraux de chaîne bruts qui vous permettent de définir votre propre terminateur

C # a ses @literals pour les chaînes multi-lignes.

Même le C simple et donc l'ancien C ++ et l'Objective-C permettent la concatentation simplement en mettant plusieurs littéraux adjacents, de sorte que les guillemets sont réduits. Les espaces ne comptent pas lorsque vous faites cela, vous pouvez donc les mettre sur des lignes différentes (mais vous devez ajouter vos propres nouvelles lignes):

const char* text = "This is some text\n"
                   "over multiple lines";

Comme swift ne sait pas que vous avez mis votre texte sur plusieurs lignes, je dois corriger l'échantillon de connor, de la même manière que mon échantillon C, en expliquant explicitement la nouvelle ligne:

var text:String = "This is some text \n" +
                  "over multiple lines"
Andy Dent
la source
4
Je suis presque sûr qu'il y a des limites à cela. J'ai essayé de diviser une chaîne sur 13 lignes (c'est un texte d'information sur plusieurs lignes). Non seulement il n'a pas fini de compiler, mais il a mis mon Mac à genoux. Comme je l'ai dit, je ne peux pas catégoriquement dire que c'est un problème, mais attention, l'impact est assez mauvais.
Derek Knight
J'ai planté plusieurs fois avant même de compiler. Je pense que le processus "SourceKitService" qui est responsable de la mise en évidence de la syntaxe et de l'achèvement du code (je suppose) est également responsable de ce plantage.
Paul Brewczynski
@DerekKnight C'est un bogue du compilateur, pas une limitation de langue. Si cela persiste, vous devez déposer un radar.
radex
@bluesm FYI: SourceKit est un processus distinct, il ne peut donc pas planter Xcode. Il fait la mise en évidence de la syntaxe et l'achèvement du code, correct, mais pour le moment, la compilation elle-même vit dans le processus de Xcode - c'est pourquoi un bogue du compilateur supprime parfois Xcode avec lui-même :(
radex
17

Les chaînes multilignes sont possibles à partir de Swift 4.0, mais il existe certaines règles:

  1. Vous devez commencer et terminer vos chaînes avec trois guillemets doubles, """ .
  2. Le contenu de votre chaîne doit commencer sur sa propre ligne.
  3. La terminaison """doit également commencer sur sa propre ligne.

A part ça, vous êtes prêt à partir! Voici un exemple:

let longString = """
When you write a string that spans multiple
lines make sure you start its content on a
line all of its own, and end it with three
quotes also on a line of their own.
Multi-line strings also let you write "quote marks"
freely inside your strings, which is great!
"""

Découvrez les nouveautés de Swift 4 pour plus d'informations.

TwoStraws
la source
Malheureusement, cela ne fonctionne pas dans une aire de jeux Xcode 8.3.3. J'obtiens une erreur "chaîne non terminée".
James Foster
Comme je l'ai dit, cette fonctionnalité est nouvelle dans Swift 4 - installez une chaîne d'outils Swift 4 dans Xcode 8.3.3 ou installez Xcode 9.
TwoStraws
16

Comme l'a souligné litso, l'utilisation répétée de +-Operator dans une expression peut entraîner un blocage de XCode Beta (juste vérifié avec XCode 6 Beta 5): Xcode 6 Beta ne compile pas

Une alternative pour les chaînes multilignes pour l'instant consiste à utiliser un tableau de chaînes et reduce cela avec +:

var text = ["This is some text ",
            "over multiple lines"].reduce("", +)

Ou, sans doute plus simple, en utilisant join:

var text = "".join(["This is some text ",
                    "over multiple lines"])
Jonas Reinsch
la source
La version réduite a fonctionné pour moi sur la bêta 6, mais la jointure a levé une exception.
Tristan Warner-Smith
9

Swift 4 a résolu ce problème en prenant en charge le littéral de chaîne multi-lignes.Pour commencer le littéral de chaîne, ajoutez trois guillemets doubles ("" ") et appuyez sur la touche Retour, après avoir appuyé sur la touche Retour, commencez à écrire des chaînes avec des variables, des sauts de ligne et des guillemets doubles. comme si vous écriviez dans le bloc-notes ou dans n'importe quel éditeur de texte. Pour terminer à nouveau le littéral de chaîne de plusieurs lignes, écrivez ("" ") dans une nouvelle ligne.

Voir l'exemple ci-dessous

     let multiLineStringLiteral = """
    This is one of the best feature add in Swift 4
    It let’s you write “Double Quotes” without any escaping
    and new lines without need of “\n”
    """

print(multiLineStringLiteral)
Nareshkumar Nil
la source
5

Rapide:

@connor est la bonne réponse, mais si vous souhaitez ajouter des lignes dans une déclaration d'impression, ce que vous recherchez est \net / ou \r, ce sont des séquences d'échappement ou des caractères échappés, il s'agit d'un lien vers la documentation Apple sur le sujet. .

Exemple:

print("First line\nSecond Line\rThirdLine...")
Juan Boero
la source
6
Ce n'est ce que personne veut. Nous voulons pouvoir avoir des retours à la ligne dans le code source pour les littéraux de chaîne, pas (nécessairement) des sauts de ligne dans la sortie rendue . C'était assez clair dans la question d'origine, je pense. Les gens avec des scores positifs ont évidemment compris. Les personnes ayant des scores négatifs ne l'ont évidemment pas fait.
ArtOfWarfare
5
@ArtOfWarfare c'est la réponse que je cherchais et cette page était le meilleur résultat lors d'une recherche de "nouvelle chaîne de ligne rapide". De toute évidence, ce n'est pas aussi évident que vous le dites.
John R Perry
4

En ajoutant à la réponse @Connor, il doit également y avoir \ n. Voici le code révisé:

var text:String = "This is some text \n" +
                  "over multiple lines"
Pandurang Yachwad
la source
3

L'exemple suivant illustre une continuation sur plusieurs lignes, utilisant des parenthèses comme solution de contournement simple pour le bogue Swift à partir de Xcode 6.2 Beta, où il se plaint que l'expression est trop complexe à résoudre dans un délai raisonnable et à envisager de la décomposer en plus petit pièces:

    .
    .
    .
    return String(format:"\n" +
                    ("    part1:    %d\n"    +
                     "    part2:    %d\n"    +
                     "    part3:  \"%@\"\n"  +
                     "    part4:  \"%@\"\n"  +
                     "    part5:  \"%@\"\n"  +
                     "    part6:  \"%@\"\n") +
                    ("    part7:  \"%@\"\n"  +
                     "    part8:  \"%@\"\n"  +
                     "    part9:  \"%@\"\n"  +
                     "    part10: \"%@\"\n"  +
                     "    part12: \"%@\"\n") +
                     "    part13:  %f\n"     +
                     "    part14:  %f\n\n",
                    part1, part2, part3, part4, part5, part6, part7, part8, 
                    part9, part10, part11, part12, part13, part14)
    .
    .
    .
clair
la source
0

Une autre façon si vous souhaitez utiliser une variable de chaîne avec du texte prédéfini,

var textFieldData:String = "John"
myTextField.text = NSString(format: "Hello User, \n %@",textFieldData) as String
myTextField.numberOfLines = 0
Zoran777
la source
0

Vous pouvez utiliser des égaux unicode pour entrer ou les \nimplémenter dans votre chaîne. Par exemple: \u{0085}.

hooman
la source
0

Échantillon

var yourString = "first line \n second line \n third line"

Dans le cas où vous ne trouvez pas l'opérateur + approprié

Danielle Cohen
la source
0

Une approche consiste à définir le texte de l'étiquette sur AttribedText et à mettre à jour la variable de chaîne pour inclure le code HTML pour le saut de ligne ( <br />).

Par exemple:

var text:String = "This is some text<br />over multiple lines"
label.attributedText = text

Production:

This is some text
over multiple lines

J'espère que cela t'aides!

B-Rad
la source
Vous ne pouvez pas affecter de Stringvaleur (texte) à la NSAttributedString?propriété (label.attributedText).
Maxime Ashurov
0

Voici un extrait de code pour diviser une chaîne par n caractères séparés sur des lignes:

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController {
    override func loadView() {

        let str = String(charsPerLine: 5, "Hello World!")
        print(str) // "Hello\n Worl\nd!\n"

    }
}

extension String {

    init(charsPerLine:Int, _ str:String){

        self = ""
        var idx = 0
        for char in str {
            self += "\(char)"
            idx = idx + 1
            if idx == charsPerLine {
                self += "\n"
                idx = 0
            }
        }

    }
}
Michael N
la source
-3

J'ai essayé plusieurs façons, mais j'ai trouvé une solution encore meilleure: utilisez simplement un élément "Affichage texte". Son texte affiche automatiquement plusieurs lignes! Trouvé ici: UITextField plusieurs lignes

Oliver Ries
la source
(juste pour que vous sachiez, les downvotes sont probablement parce que la question portait sur le formatage en code, pas dans l'interface utilisateur ... et fournir un exemple de code dans votre réponse aurait probablement rendu cela plus apparent)
benc