Swift - String über mehrere Zeilen teilen


265

Wie kann ich eine Zeichenfolge über mehrere Zeilen wie unten aufteilen?

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

Informationen zum automatischen Konvertieren von Zeilen in eine mehrzeilige Zeichenfolge finden Sie in meiner Antwort zu diesem leicht verwandten Thread. Wie können Sie dieses mehrzeilige Zeichenfolgenliteralmakro in Swift implementieren?
Holroy

Antworten:


444

Swift 4 unterstützt mehrzeilige String-Literale . Neben Zeilenumbrüchen können sie auch Anführungszeichen enthalten.

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

In älteren Versionen von Swift können Sie kein einzelnes Literal über mehrere Zeilen hinweg erstellen, aber Sie können Literale über mehrere Zeilen hinweg hinzufügen:

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

2
Das Problem bei diesem Ansatz ist, dass Sie in Swift (ab Xcode 6.2 Beta) leicht zu viele "fortgesetzte" Zeilen erreichen können, in denen der Ausdruck "zu komplex, um in angemessener Zeit gelöst zu werden" und das Brechen in Betracht gezogen wird es geht um einfachere Ausdrücke. Das ist hässlich, aber leicht zu erreichen. Wickeln Sie einfach Abschnitte in Parens.
Clearlight

8
Vergessen Sie nicht, ein Leerzeichen zwischen dem Schlusszitat und dem + einzufügen, da sonst der Fehler "'+' ist kein unärer Postfix-Operator" angezeigt wird
Orlin Georgiev,

Dies funktioniert immer noch, aber Sie müssen das \nZeichen manuell hinzufügen . Zum Beispiel in der REPL: println("foo\n" + "bar")druckt foound barin separaten Zeilen.
Brian Gerstle

Es sollte in Xcode 7 behoben werden. "Die Verkettung von Swift-String-Literalen, auch über mehrere Zeilen hinweg, ist eine garantierte Optimierung der Kompilierungszeit, auch bei -Onone." Adcdownload.apple.com/WWDC_2015/Xcode_7_beta/…
Kostiantyn Koval

2
Funktioniert nicht für Enum-Case-Werte, die Zeichenfolgen verwenden :(
Lars Blumberg

32

Ich habe eine Erweiterung für String verwendet, um mehrzeilige Strings zu erzielen und gleichzeitig den Fehler beim Hängen des Compilers zu vermeiden. Außerdem können Sie ein Trennzeichen angeben, damit Sie es ähnlich wie die Join-Funktion von Python verwenden können

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
Diese Methoden sind perfekt. Selbst in der neuesten Version von 1.2 Swift werden lange Literale sehr langsam kompiliert, und diese Methoden vermeiden diesen Overhead.
Phatmann

2
Für alle, die Swift 2 verwenden, enumerate(lines)ist jetztlines.enumerate()
Jedidja

2
@mcornell Das ist schön, macht aber nicht im joinWithSeparatorWesentlichen das Gleiche? ["Hello", "World!"].joinWithSeparator(", ")
Dan Loewenherz

27

Dies war die erste enttäuschende Sache an Swift, die mir auffiel. Fast alle Skriptsprachen ermöglichen mehrzeilige Zeichenfolgen.

In C ++ 11 wurden Raw-String-Literale hinzugefügt, mit denen Sie Ihren eigenen Terminator definieren können

C # hat seine @ Literale für mehrzeilige Zeichenfolgen.

Sogar einfaches C und damit altmodisches C ++ und Objective-C ermöglichen eine Konzentration, indem einfach mehrere Literale nebeneinander platziert werden, sodass Anführungszeichen reduziert werden. Whitespace zählt dabei nicht, sodass Sie sie in verschiedene Zeilen einfügen können (Sie müssen jedoch Ihre eigenen Zeilenumbrüche hinzufügen):

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

Da Swift nicht weiß, dass Sie Ihren Text über mehrere Zeilen geschrieben haben, muss ich das Connor-Beispiel ähnlich wie mein C-Beispiel korrigieren und die neue Zeile explizit angeben:

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

4
Ich bin mir ziemlich sicher, dass dies Einschränkungen mit sich bringt. Ich habe versucht, eine Zeichenfolge auf 13 Zeilen aufzuteilen (es handelt sich um einen mehrzeiligen Infotext). Es konnte nicht nur das Kompilieren nicht beenden, sondern brachte meinen Mac auch in die Knie. Wie gesagt, ich kann nicht kategorisch sagen, dass dies ein Problem ist, aber Vorsicht, die Auswirkungen sind ziemlich schlimm.
Derek Knight

Ich bin schon vor dem Kompilieren mehrmals abgestürzt. Ich denke, dass der "SourceKitService" -Prozess, der für die Syntaxhervorhebung und die Code-Vervollständigung verantwortlich ist (ich nehme an), auch für diese Abstürze verantwortlich ist.
Paul Brewczynski

@DerekKnight Das ist ein Compiler-Fehler, keine Sprachbeschränkung. Wenn es weiterhin besteht, sollten Sie ein Radar einreichen.
Radex

@bluesm FYI: SourceKit ist ein separater Prozess, sodass Xcode nicht abstürzen kann. Es macht Syntaxhervorhebung und Code-Vervollständigung richtig, aber im Moment lebt die Kompilierung selbst im Prozess von Xcode - deshalb entfernt ein Compiler-Fehler Xcode manchmal mit sich selbst :(
Radex

17

Ab Swift 4.0 sind mehrzeilige Zeichenfolgen möglich, es gibt jedoch einige Regeln:

  1. Sie müssen Ihre Zeichenfolgen mit drei doppelten Anführungszeichen beginnen und beenden """.
  2. Ihr String-Inhalt sollte in einer eigenen Zeile beginnen.
  3. Die Beendigung """sollte auch in einer eigenen Zeile beginnen.

Davon abgesehen können Sie loslegen! Hier ist ein Beispiel:

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

Sehen Sie, was in Swift 4 ist neu für weitere Informationen.


Leider funktioniert dies auf einem Xcode 8.3.3-Spielplatz nicht. Ich erhalte den Fehler "nicht abgeschlossene Zeichenfolge".
James Foster

Wie gesagt, diese Funktion ist neu in Swift 4 - entweder installieren Sie eine Swift 4-Toolchain in Xcode 8.3.3 oder installieren Sie Xcode 9.
TwoStraws

16

Wie von litso hervorgehoben, kann die wiederholte Verwendung des +-Operators in einem Ausdruck dazu führen, dass XCode Beta hängt (nur mit XCode 6 Beta 5 überprüft): Xcode 6 Beta wird nicht kompiliert

Eine Alternative für mehrzeilige Zeichenfolgen besteht derzeit darin, ein Array von Zeichenfolgen zu verwenden, und zwar reducemit +:

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

Oder, wohl einfacher, mit join:

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

Die reduzierte Version funktionierte für mich in Beta 6, aber der Join warf eine Ausnahme.
Tristan Warner-Smith

9

Swift 4 hat dieses Problem behoben, indem es mehrzeiliges Zeichenfolgenliteral unterstützt. Um mit dem Zeichenfolgenliteral zu beginnen, fügen Sie drei doppelte Anführungszeichen (”” ”) hinzu und drücken Sie die Eingabetaste. Nachdem Sie die Eingabetaste gedrückt haben, schreiben Sie Zeichenfolgen mit beliebigen Variablen, Zeilenumbrüchen und doppelten Anführungszeichen als würden Sie in Notizblock oder einem beliebigen Texteditor schreiben. Um das mehrzeilige Zeichenfolgenliteral erneut zu beenden, schreiben Sie (”” ”) in eine neue Zeile.

Siehe Beispiel unten

     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

Schnell:

@connor ist die richtige Antwort. Wenn Sie jedoch Zeilen in einer Druckanweisung hinzufügen möchten, nach denen Sie suchen, \nund / oder \rdiese als Escape-Sequenzen oder Escap-Zeichen bezeichnet werden, ist dies ein Link zur Apple-Dokumentation zu diesem Thema. .

Beispiel:

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

6
Das will niemand. Wir möchten in der Lage sein, Zeilenumbrüche im Quellcode für die Zeichenfolgenliterale zu haben, nicht (notwendigerweise) Zeilenumbrüche in der gerenderten Ausgabe . Das war in der ursprünglichen Frage ziemlich klar, denke ich. Menschen mit positiven Ergebnissen verstanden offensichtlich. Menschen mit negativen Bewertungen taten dies offensichtlich nicht.
ArtOfWarfare

5
@ArtOfWarfare Dies ist die Antwort, nach der ich gesucht habe, und diese Seite war das beste Ergebnis bei der Suche nach "new line swift string". Offensichtlich ist es nicht so offensichtlich, wie Sie sagen.
John R Perry

4

Zum Hinzufügen zur @ Connor-Antwort muss auch \ n vorhanden sein. Hier ist überarbeiteter Code:

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

3

Das folgende Beispiel zeigt eine mehrzeilige Fortsetzung, wobei Klammern als einfache Problemumgehung für den Swift-Fehler ab Xcode 6.2 Beta verwendet werden. Dabei wird beanstandet, dass der Ausdruck zu komplex ist, um ihn in angemessener Zeit aufzulösen und in kleinere Teile zu zerlegen Stücke:

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

Eine andere Möglichkeit, wenn Sie eine Zeichenfolgenvariable mit vordefiniertem Text verwenden möchten,

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

0

Sie können Unicode-Gleichungen für die Eingabe oder \nImplementierung in Ihrer Zeichenfolge verwenden. Zum Beispiel : \u{0085}.


0

Stichprobe

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

Falls Sie den Operator + nicht für geeignet halten


0

Ein Ansatz besteht darin, den Beschriftungstext auf attributedText zu setzen und die Zeichenfolgenvariable so zu aktualisieren, dass sie den HTML-Code für Zeilenumbruch ( <br />) enthält.

Beispielsweise:

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

Ausgabe:

This is some text
over multiple lines

Hoffe das hilft!


Sie können Stringder NSAttributedString?Eigenschaft (label.attributedText) keinen Wert (Text) zuweisen.
Maxime Ashurov

0

Hier ist ein Code-Snippet zum Teilen einer Zeichenfolge durch n Zeichen, die über Zeilen getrennt sind:

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

Ich habe verschiedene Möglichkeiten ausprobiert, aber eine noch bessere Lösung gefunden: Verwenden Sie einfach ein "Textansicht" -Element. Der Text wird automatisch in mehreren Zeilen angezeigt! Hier gefunden: UITextField mehrere Zeilen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.