Swift - Dividi la stringa su più righe


Risposte:


444

Swift 4 include il supporto per i letterali di stringa multilinea . Oltre alle newline possono contenere anche virgolette senza caratteri di escape.

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

Le versioni precedenti di Swift non ti consentono di avere un solo valore letterale su più righe ma puoi aggiungere valori letterali su più righe:

var text = "This is some text\n"
         + "over multiple lines\n"

2
Il problema con questo approccio è che puoi facilmente raggiungere troppe righe "continue" in Swift (a partire da Xcode 6.2 beta), dove si lamenta che l'espressione è "troppo complessa per essere risolta in un ragionevole lasso di tempo" e considerare la possibilità di interrompere fino a espressioni più semplici. È brutto ma abbastanza facile da realizzare, basta avvolgere le sezioni in parentesi.
Clearlight il

8
Non dimenticare di aggiungere uno spazio tra la virgoletta di chiusura e il +, altrimenti otterrai un errore "'+' non è un operatore unario postfisso"
Orlin Georgiev

Funziona ancora, ma è necessario aggiungere manualmente il \npersonaggio. Ad esempio, nel REPL: println("foo\n" + "bar")stampa fooe barsu righe separate.
Brian Gerstle,

Dovrebbe essere risolto in Xcode 7 "La concatenazione dei letterali di stringa Swift, anche su più righe, è un'ottimizzazione del tempo di compilazione garantita, anche su -Onone.", Adcdownload.apple.com/WWDC_2015/Xcode_7_beta/…
Kostiantyn Koval

2
Non funziona con i valori di case enum che usano stringhe :(
Lars Blumberg,

32

Ho usato un'estensione su String per ottenere stringhe multilinea evitando il bug di sospensione del compilatore. Ti permette anche di specificare un separatore in modo da poterlo usare un po 'come la funzione join di 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!"

1
Questi metodi sono perfetti. Anche nell'ultima versione 1.2 di Swift i letterali lunghi vengono compilati molto lentamente e questi metodi evitano questo sovraccarico.
Phatmann,

2
Per chiunque utilizzi Swift 2, enumerate(lines)è oralines.enumerate()
Jedidja il

2
@mcornell Questo è carino, ma joinWithSeparatorsostanzialmente non fa la stessa cosa? ["Hello", "World!"].joinWithSeparator(", ")
Dan Loewenherz,

27

Questa è stata la prima cosa deludente di Swift che ho notato. Quasi tutti i linguaggi di scripting consentono stringhe multilinea.

C ++ 11 ha aggiunto valori letterali di stringa non elaborati che consentono di definire il proprio terminatore

C # ha i suoi @literals per stringhe multilinea.

Anche la semplice C e quindi il vecchio stile C ++ e Objective-C consentono la concatenazione semplicemente mettendo più letterali adiacenti, quindi le virgolette vengono compresse. Lo spazio bianco non conta quando lo fai in modo da poterli mettere su linee diverse (ma è necessario aggiungere le tue nuove linee):

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

Poiché swift non sa che hai inserito il tuo testo su più righe, devo correggere l'esempio di Connor, in modo simile al mio esempio C, dichiarando esplicitamente la nuova riga:

var text:String = "This is some text \n" +
                  "over multiple lines"

4
Sono abbastanza sicuro che ci siano delle limitazioni in questo. Ho provato a dividere una stringa su 13 righe (è un testo informativo a più righe). Non solo non è riuscito a completare la compilazione, ma ha messo in ginocchio il mio Mac. Come ho già detto, non posso dire categoricamente che si tratta di un problema, ma attenzione, l'impatto è piuttosto negativo.
Derek Knight,

Mi sono schiantato più volte anche prima di compilare. Penso che anche il processo "SourceKitService" responsabile dell'evidenziazione della sintassi e del completamento del codice (suppongo) sia responsabile di questi arresti anomali.
Paul Brewczynski,

@DerekKnight Questo è un bug del compilatore, non una limitazione della lingua. Se persiste ancora, dovresti presentare un radar.
Radex,

@bluesm FYI: SourceKit è un processo separato, quindi non può bloccare Xcode. Esegue l'evidenziazione della sintassi e il completamento del codice, corretto, ma al momento, la compilazione stessa vive nel processo di Xcode - ecco perché un bug del compilatore elimina Xcode con se stesso a volte :(
radex

17

Le stringhe multilinea sono disponibili a partire da Swift 4.0, ma ci sono alcune regole:

  1. È necessario iniziare e terminare le stringhe con tre doppi apici, """.
  2. Il contenuto della stringa dovrebbe iniziare su una riga separata.
  3. La terminazione """dovrebbe anche iniziare su una propria linea.

A parte questo, sei a posto! Ecco un esempio:

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!
"""

Vedere le novità di Swift 4 per ulteriori informazioni.


Sfortunatamente questo non funziona in un Xcode 8.3.3 Playground. Viene visualizzato l'errore "stringa non terminata".
James Foster,

Come ho già detto, questa funzione è nuova in Swift 4: installa una toolchain Swift 4 in Xcode 8.3.3 o installa Xcode 9.
TwoStraws

16

Come sottolineato da litso, l'uso ripetuto di +-Operator in un'espressione può portare a un blocco di XCode Beta (appena verificato con XCode 6 Beta 5): Xcode 6 Beta non compilato

Un'alternativa per le stringhe multilinea per ora è usare una matrice di stringhe e reducecon +:

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

O, probabilmente più semplice, usando join:

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

La versione ridotta ha funzionato per me su beta 6, ma il join ha generato un'eccezione.
Tristan Warner-Smith,

9

Swift 4 ha risolto questo problema fornendo supporto letterale a più righe. Per iniziare a creare stringhe letterali aggiungere tre virgolette doppie ("" ") e premere il tasto Invio, dopo aver premuto il tasto Ritorno iniziare a scrivere stringhe con qualsiasi variabile, interruzioni di riga e virgolette doppie come se scrivessi nel blocco note o in qualsiasi editor di testo. Per terminare di nuovo il valore letterale della stringa di più righe, scrivere ("" ") in una nuova riga.

Vedi sotto esempio

     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)

5

Swift:

@connor è la risposta giusta, ma se si desidera aggiungere righe in un'istruzione di stampa ciò che si sta cercando è \ne / o \r, queste sono chiamate sequenze di escape o caratteri di escape, questo è un collegamento alla documentazione Apple sull'argomento..

Esempio:

print("First line\nSecond Line\rThirdLine...")

6
Questo non è quello che qualcuno vuole. Vogliamo poter essere in grado di includere gli avvolgimenti di riga nel codice sorgente per i letterali di stringa, non (necessariamente) avere interruzioni di riga nell'output di rendering . Questo era abbastanza chiaro nella domanda originale, penso. Le persone con punteggi positivi hanno ovviamente capito. Le persone con punteggi negativi ovviamente no.
ArtOfWarfare

5
@ArtOfWarfare questa è la risposta che stavo cercando e questa pagina è stata il miglior risultato quando ho fatto una ricerca per "stringa nuova riga veloce". Ovviamente, non è così ovvio come dici tu.
John R Perry,

4

Aggiungendo alla risposta @Connor, ci deve essere anche \ n. Ecco il codice rivisto:

var text:String = "This is some text \n" +
                  "over multiple lines"

3

L'esempio seguente mostra una continuazione su più righe, usando la parentesi come semplice soluzione per il bug Swift a partire da Xcode 6.2 Beta, dove si lamenta che l'espressione è troppo complessa per essere risolta in un tempo ragionevole e per considerare di scomporla in più piccola pezzi:

    .
    .
    .
    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)
    .
    .
    .

0

Un altro modo se desideri utilizzare una variabile stringa con del testo predefinito,

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

0

Puoi usare unicode uguale a enter o \ne implementarli all'interno della tua stringa. Ad esempio: \u{0085}.


0

Campione

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

Nel caso, non trovi l'operatore + adatto


0

Un approccio consiste nell'impostare il testo dell'etichetta su attributiText e aggiornare la variabile stringa per includere l'HTML per l'interruzione di riga (<br /> ).

Per esempio:

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

Produzione:

This is some text
over multiple lines

Spero che questo ti aiuti!


Non è possibile assegnare Stringvalore (testo) alla NSAttributedString?proprietà (label.attributedText).
Maxime Ashurov,

0

Ecco uno snippet di codice per dividere una stringa per n caratteri separati su righe:

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

    }
}

-3

Ho provato diversi modi, ma ho trovato una soluzione ancora migliore: basta usare un elemento "Visualizzazione testo". Il suo testo mostra automaticamente più righe! Trovato qui: UITextField più righe


(solo per questo sai, i downvotes sono probabilmente perché la domanda riguardava la formattazione del codice, non nell'interfaccia utente ... e fornire un esempio di codice nella tua risposta avrebbe probabilmente reso questo più evidente)
benc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.