Swift - Divide a string em várias linhas

Respostas:

444

O Swift 4 inclui suporte para literais de strings de várias linhas . Além das novas linhas, elas também podem conter aspas sem escape.

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

As versões anteriores do Swift não permitem que você tenha um único literal em várias linhas, mas você pode adicionar literais em várias linhas:

var text = "This is some text\n"
         + "over multiple lines\n"
Connor
fonte
2
O problema com essa abordagem é que você pode facilmente acessar muitas linhas 'contínuas' no Swift (a partir do Xcode 6.2 beta), onde reclama que a expressão é "complexa demais para ser resolvida em um período de tempo razoável" e considerar a possibilidade de quebrar até expressões mais simples. Isso é feio, mas fácil o suficiente, basta envolver as seções em parênteses.
clearlight
8
Não se esqueça de adicionar um espaço entre a citação de fechamento e o +, caso contrário, você receberá um erro "'+' não é um operador unificado pós-fixado"
Orlin Georgiev
Isso ainda funciona, mas você precisa adicionar manualmente o \npersonagem. Por exemplo, no REPL: println("foo\n" + "bar")imprime fooe barem linhas separadas.
9789 Brian Gerstle às
Ele deve ser corrigido no Xcode 7 "Concatenação de literais de cadeia Swift, incluindo várias linhas, é uma otimização garantida em tempo de compilação, mesmo em -Onone.", Adcdownload.apple.com/WWDC_2015/Xcode_7_beta/…
Kostiantyn Koval
2
Não funciona para valores de maiúsculas e minúsculas que usam seqüências de caracteres :(
Lars Blumberg
32

Eu usei uma extensão no String para obter seqüências de múltiplas linhas, evitando o bug de suspensão do compilador. Também permite especificar um separador para que você possa usá-lo um pouco como a função de junção do 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!"
McCornell
fonte
1
Esses métodos são perfeitos. Mesmo na versão mais recente do 1.2 Swift, literais longos são compilados muito lentamente, e esses métodos evitam essa sobrecarga.
Phatmann
2
Para quem usa o Swift 2, enumerate(lines)agora élines.enumerate()
Jedidja 30/09
2
@mcornell Isso é legal, mas não joinWithSeparatorfaz essencialmente a mesma coisa? ["Hello", "World!"].joinWithSeparator(", ")
Dan Loewenherz
27

Esta foi a primeira coisa decepcionante sobre Swift que eu notei. Quase todas as linguagens de script permitem seqüências de várias linhas.

O C ++ 11 adicionou literais de cadeia bruta que permitem definir seu próprio terminador

O C # tem seus @ literais para seqüências de caracteres de várias linhas.

Mesmo C simples e, portanto, C ++ e Objective-C antiquados permitem concatentação simplesmente colocando vários literais adjacentes, para que as aspas sejam recolhidas. O espaço em branco não conta quando você faz isso, para poder colocá-los em linhas diferentes (mas precisa adicionar suas próprias novas linhas):

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

Como o swift não sabe que você colocou seu texto em várias linhas, eu tenho que corrigir a amostra de connor, da mesma forma que a minha amostra C, declarando explicitamente a nova linha:

var text:String = "This is some text \n" +
                  "over multiple lines"
Andy Dent
fonte
4
Tenho certeza de que existem limitações nisso. Tentei dividir uma string por 13 linhas (é um texto informativo com várias linhas). Não só não conseguiu terminar de compilar, mas também deixou meu Mac de joelhos. Como eu disse, não posso categoricamente dizer que isso é um problema, mas cuidado, o impacto é muito ruim.
Derek Cavaleiro
Eu bati várias vezes antes mesmo de compilar. Eu acho que o processo "SourceKitService", que é responsável pelo destaque da sintaxe e pela conclusão do código (suponho), também é responsável por essas falhas.
Paul Brewczynski
@DerekKnight Isso é um bug do compilador, não uma limitação de idioma. Se ainda persistir, você deve enviar um radar.
Radex
@bluesm FYI: O SourceKit é um processo separado, portanto não pode travar o Xcode. Ele faz destaque de sintaxe e conclusão de código, correto, mas, no momento, a própria compilação vive em processo de Xcode - é por isso que um erro do compilador leva para baixo Xcode com ele mesmo, por vezes :(
RADEX
17

Cadeias de linhas múltiplas são possíveis a partir do Swift 4.0, mas existem algumas regras:

  1. Você precisa iniciar e terminar suas strings com três aspas duplas """,.
  2. O conteúdo da string deve começar em sua própria linha.
  3. A terminação """também deve começar em sua própria linha.

Fora isso, você está pronto para ir! Aqui está um exemplo:

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

Veja o que há de novo no Swift 4 para obter mais informações.

TwoStraws
fonte
Infelizmente, isso não funciona no Xcode 8.3.3 Playground. Eu recebo um erro "string não terminada".
James Foster
Como eu disse, esse recurso é novo no Swift 4 - instale um Swift 4 toolchain em Xcode 8.3.3 ou instalar Xcode 9.
TwoStraws
16

Conforme apontado por litso, o uso repetido do +-Operator em uma expressão pode levar à suspensão do XCode Beta (apenas verificado com o XCode 6 Beta 5): Xcode 6 Beta não compilando

Uma alternativa para cadeias de linhas múltiplas por enquanto é usar uma matriz de cadeias e reducecom +:

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

Ou, sem dúvida mais simples, usando join:

var text = "".join(["This is some text ",
                    "over multiple lines"])
Jonas Reinsch
fonte
A versão reduzida funcionou para mim no beta 6, mas a junção lançou uma exceção.
Tristan Warner-Smith
9

O Swift 4 resolveu esse problema, oferecendo suporte literal para várias linhas. Para iniciar o literal de cadeia, adicione três aspas duplas (”” ”) e pressione a tecla Enter. Depois de pressionar a tecla Enter, comece a escrever strings com quaisquer variáveis, quebras de linha e aspas duplas. como você escreveria no bloco de notas ou em qualquer editor de texto. Para finalizar literalmente a sequência de várias linhas, escreva (”” ”) na nova linha.

Veja abaixo o exemplo

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

Rápido:

@connor é a resposta certa, mas se você deseja adicionar linhas em uma declaração impressa, o que você está procurando é \ne / ou \ré chamado Sequências de escape ou Caracteres escapados, este é um link para a documentação da Apple sobre o assunto. .

Exemplo:

print("First line\nSecond Line\rThirdLine...")
Juan Boero
fonte
6
Não é isso que alguém quer. Queremos poder ter quebra de linha no código-fonte para os literais de string, não (necessariamente) ter quebras de linha na saída renderizada . Isso ficou bem claro na pergunta original, eu acho. Pessoas com resultados positivos obviamente entenderam. Pessoas com resultados negativos obviamente não o fizeram.
ArtOfWarfare
5
@ArtOfWarfare, esta é a resposta que eu estava procurando e esta página foi o resultado principal ao fazer uma pesquisa por "nova linha de seqüência rápida". Obviamente, não é tão óbvio como você diz.
John R Perry
4

Adicionando à resposta @Connor, também precisa haver \ n. Aqui está o código revisado:

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

O exemplo a seguir mostra uma continuação de várias linhas, usando parênteses como uma solução alternativa simples para o bug Swift a partir do Xcode 6.2 Beta, em que reclama que a expressão é complexa demais para ser resolvida em um período de tempo razoável e considerar a decomposição em menor peças:

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

Outra maneira, se você quiser usar uma variável de string com algum texto predefinido,

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

Você pode usar iguais unicode para inserir ou \nimplementá-los dentro de sua string. Por exemplo: \u{0085}.

hooman
fonte
0

Amostra

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

Caso não encontre o operador + adequado

Danielle Cohen
fonte
0

Uma abordagem é definir o texto do rótulo como attributeText e atualizar a variável de sequência para incluir o HTML para quebra de linha ( <br />).

Por exemplo:

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

Resultado:

This is some text
over multiple lines

Espero que isto ajude!

B-Rad
fonte
Você não pode atribuir Stringvalor (texto) à NSAttributedString?propriedade (label.attributedText).
Maxime Ashurov
0

Aqui está um trecho de código para dividir uma string por n caracteres separados por linhas:

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

Tentei de várias maneiras, mas encontrei uma solução ainda melhor: basta usar o elemento "Visualização de texto". Seu texto mostra várias linhas automaticamente! Encontrado aqui: UITextField várias linhas

Oliver Ries
fonte
(só para você saber, os votos negativos são provavelmente porque a pergunta era sobre formatação de código, não na interface do usuário… e fornecer um exemplo de código em sua resposta provavelmente tornaria isso mais aparente)
benc