Swift: divide la cadena en varias líneas

Respuestas:

444

Swift 4 incluye soporte para literales de cadena de varias líneas . Además de las nuevas líneas, también pueden contener citas sin escape.

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

Las versiones anteriores de Swift no le permiten tener un solo literal en varias líneas, pero puede agregar literales en varias líneas:

var text = "This is some text\n"
         + "over multiple lines\n"
Connor
fuente
2
El problema con ese enfoque es que puede alcanzar fácilmente demasiadas líneas 'continuas' en Swift (a partir de Xcode 6.2 beta), donde se queja de que la expresión es "demasiado compleja para ser resuelta en un período de tiempo razonable" y para considerar romper abajo a expresiones más simples. Eso es feo pero lo suficientemente fácil de lograr, solo envuelva las secciones en parens.
clearlight
8
No olvide agregar un espacio entre la cita de cierre y el +, de lo contrario obtendrá un error "'+' no es un operador unario postfix"
Orlin Georgiev
Esto aún funciona, pero debe agregar manualmente el \ncarácter. Por ejemplo, en REPL: println("foo\n" + "bar")imprime fooy baren líneas separadas.
Brian Gerstle
Se debe corregir en Xcode 7 "La concatenación de literales de cadena Swift, incluso a través de varias líneas, es una optimización de tiempo de compilación garantizada, incluso en -Onone.", Adcdownload.apple.com/WWDC_2015/Xcode_7_beta/…
Kostiantyn Koval
2
No funciona para valores de mayúsculas y minúsculas que usan cadenas :(
Lars Blumberg
32

Usé una extensión en String para lograr cadenas multilínea mientras evitaba el error de compilación. También le permite especificar un separador para que pueda usarlo un poco como la función de combinación 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
fuente
1
Estos métodos son perfectos. Incluso en la última versión de 1.2 Swift, los literales largos se compilan muy lentamente, y estos métodos evitan esa sobrecarga.
phatmann
2
Para cualquiera que use Swift 2, enumerate(lines)ahora eslines.enumerate()
Jedidja el
2
@mcornell Esto es bueno, pero ¿no joinWithSeparatorhace esencialmente lo mismo? ["Hello", "World!"].joinWithSeparator(", ")
Dan Loewenherz
27

Esta fue la primera cosa decepcionante sobre Swift que noté. Casi todos los lenguajes de secuencias de comandos permiten cadenas de varias líneas.

C ++ 11 agregó literales de cadena sin procesar que le permiten definir su propio terminador

C # tiene sus @literals para de varias líneas.

Incluso C simple y, por lo tanto, C ++ anticuado y Objective-C permiten la concatenación simplemente colocando múltiples literales adyacentes, por lo que las comillas se contraen. Los espacios en blanco no cuentan cuando lo hace, por lo que puede colocarlos en diferentes líneas (pero necesita agregar sus propias nuevas líneas):

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

Como Swift no sabe que ha puesto su texto en varias líneas, tengo que arreglar la muestra de Connor, de manera similar a mi muestra C, indicando explícitamente la nueva línea:

var text:String = "This is some text \n" +
                  "over multiple lines"
Andy Dent
fuente
44
Estoy bastante seguro de que hay limitaciones en esto. He intentado dividir una cadena en 13 líneas (es un texto de información de varias líneas). No solo no pudo terminar de compilar, sino que también puso de rodillas a mi Mac. Como digo, no puedo decir categóricamente que este es un problema, pero cuidado, el impacto es bastante malo.
Derek Knight
Me he caído varias veces incluso antes de compilar. Creo que el proceso "SourceKitService" que es responsable del resaltado de sintaxis y la finalización del código (supongo) también es responsable de estos bloqueos.
Paul Brewczynski
@DerekKnight Eso es un error del compilador, no una limitación de idioma. Si aún persiste, debe presentar un radar.
radex
@bluesm FYI: SourceKit es un proceso separado, por lo que no puede bloquear Xcode. Realiza el resaltado de sintaxis y la finalización del código, correcto, pero en este momento, la compilación en sí misma vive en el proceso de Xcode, es por eso que un error del compilador elimina Xcode consigo mismo a veces :(
radex
17

Las cadenas de varias líneas son posibles a partir de Swift 4.0, pero hay algunas reglas:

  1. Es necesario para iniciar y finalizar sus cuerdas con tres comillas dobles, """.
  2. El contenido de su cadena debe comenzar en su propia línea.
  3. La terminación """también debe comenzar en su propia línea.

Aparte de eso, ¡estás listo para irte! Aquí hay un ejemplo:

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

Vea las novedades en Swift 4 para obtener más información.

TwoStraws
fuente
Lamentablemente, esto no funciona en un Xcode 8.3.3 Playground. Me sale un error de "cadena no terminada".
James Foster
Como dije, esta característica es nueva en Swift 4: instale una cadena de herramientas Swift 4 en Xcode 8.3.3 o instale Xcode 9.
TwoStraws
16

Como lo señaló litso, el uso repetido del +operador -Operator en una expresión puede provocar que XCode Beta se cuelgue (solo se verificó con XCode 6 Beta 5): Xcode 6 Beta no se compila

Una alternativa para las cadenas multilínea por ahora es usar una matriz de cadenas y reducecon +:

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

O, posiblemente más simple, usando join:

var text = "".join(["This is some text ",
                    "over multiple lines"])
Jonas Reinsch
fuente
La versión reducida funcionó para mí en beta 6, pero la combinación arrojó una excepción.
Tristan Warner-Smith
9

Swift 4 ha abordado este problema dando soporte literal de cadena de línea múltiple. Para comenzar el literal de cadena, agregue tres comillas dobles ("" ") y presione la tecla de retorno, después de presionar la tecla de retorno comience a escribir cadenas con cualquier variable, saltos de línea y comillas dobles solo como si escribieras en el bloc de notas o en cualquier editor de texto. Para finalizar el literal de cadena de varias líneas nuevamente, escriba (”” ”) en una nueva línea.

Ver abajo el ejemplo

     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
fuente
5

Rápido:

@connor es la respuesta correcta, pero si desea agregar líneas en una declaración impresa, lo que está buscando es \ny / o \r, estas se llaman Secuencias de escape o Caracteres escapados, este es un enlace a la documentación de Apple sobre el tema. .

Ejemplo:

print("First line\nSecond Line\rThirdLine...")
Juan boero
fuente
66
Esto no es lo que nadie quiere. Queremos poder tener ajustes de línea en el código fuente para los literales de cadena, no (necesariamente) tener saltos de línea en la salida representada . Esto fue bastante claro en la pregunta original, creo. Las personas con puntajes positivos obviamente entendieron. Las personas con puntajes negativos obviamente no lo hicieron.
ArtOfWarfare
55
@ArtOfWarfare esta es la respuesta que estaba buscando y esta página fue el mejor resultado al hacer una búsqueda de "nueva cadena de línea rápida". Obviamente, no es tan obvio como dices.
John R Perry
4

Agregando a la respuesta @Connor, también debe haber \ n. Aquí está el código revisado:

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

El siguiente ejemplo muestra una continuación de varias líneas, usando paréntesis como una solución simple para el error de Swift a partir de Xcode 6.2 Beta, donde se queja de que la expresión es demasiado compleja para resolverla en un tiempo razonable y considerar dividirla en una menor piezas:

    .
    .
    .
    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)
    .
    .
    .
luz clara
fuente
0

Otra forma si desea utilizar una variable de cadena con texto predefinido,

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

Puede usar unicode igual para ingresar o \nimplementarlos dentro de su cadena. Por ejemplo: \u{0085}.

hooman
fuente
0

Muestra

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

En caso de que no encuentre el operador + adecuado

Danielle Cohen
fuente
0

Un enfoque es establecer el texto de la etiqueta en atributeTexto y actualizar la variable de cadena para incluir el HTML para el salto de línea ( <br />).

Por ejemplo:

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

Salida:

This is some text
over multiple lines

¡Espero que esto ayude!

Puntilla
fuente
No puede asignar Stringvalor (texto) a la NSAttributedString?propiedad (label.attributedText).
Maxime Ashurov
0

Aquí hay un fragmento de código para dividir una cadena por n caracteres separados sobre líneas:

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

Lo intenté de varias maneras, pero encontré una solución aún mejor: simplemente use el elemento "Vista de texto". ¡Su texto muestra múltiples líneas automáticamente! Encontrado aquí: UITextField líneas múltiples

Oliver Ries
fuente
(para que lo sepas, los votos negativos probablemente se deben a que la pregunta era sobre formatear en código, no en la interfaz de usuario ... y proporcionar una muestra de código en tu respuesta probablemente habría hecho esto más evidente)
benc