Swift - разбить строку на несколько строк

265

Как можно разбить строку на несколько строк, как показано ниже?

var text:String = "This is some text
                   over multiple lines"
Андрей Денищик
источник
Чтобы автоматически преобразовать строки в многострочную строку, см. Мой ответ в этой слегка связанной теме. Как реализовать этот литерал-макрос многострочной строки в Swift?
Holroy
Свифт версия
Хуан Боэро

Ответы:

444

Swift 4 включает поддержку многострочных строковых литералов . В дополнение к новым строкам они также могут содержать неэкранированные кавычки.

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

Более старые версии Swift не позволяют вам иметь один литерал в несколько строк, но вы можете добавлять литералы вместе в несколько строк:

var text = "This is some text\n"
         + "over multiple lines\n"
Коннор
источник
2
Проблема с этим подходом состоит в том, что вы можете легко найти слишком много «продолженных» строк в Swift (начиная с бета-версии Xcode 6.2), где он жалуется, что выражение «слишком сложное, чтобы его можно было решить за разумное время», и можно подумать это до более простых выражений. Это некрасиво, но достаточно легко сделать, просто заверните разделы в скобки.
ясный свет
8
Не забудьте добавить пробел между закрывающей кавычкой и +, в противном случае вы получите ошибку "+" не является унарным постфиксным оператором "
Орлин Георгиев
Это все еще работает, но вам нужно вручную добавить \nперсонажа. Например, в REPL: println("foo\n" + "bar")печатается fooи barна отдельных строках.
Брайан Герстл
Это должно быть исправлено в Xcode 7 "Конкатенация строковых литералов Swift, включая несколько строк, является гарантированной оптимизацией во время компиляции, даже при -Onone.," Adcdownload.apple.com/WWDC_2015/Xcode_7_beta/…
Константин Коваль,
2
Не работает для значений перечисления, которые используют строки :(
Ларс Блумберг
32

Я использовал расширение для String для достижения многострочных строк, избегая при этом ошибки зависания компилятора. Это также позволяет вам указать разделитель, чтобы вы могли использовать его немного как функцию соединения 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
источник
1
Эти методы идеальны. Даже в последнем выпуске 1.2 Swift длинные литералы компилируются очень медленно, и эти методы позволяют избежать этих накладных расходов.
phatmann
2
Для тех, кто использует Swift 2, enumerate(lines)сейчасlines.enumerate()
Джедиджа
2
@mcornell Это хорошо, но разве это не joinWithSeparatorодно и то же? ["Hello", "World!"].joinWithSeparator(", ")
Дэн Левенхерц
27

Это была первая разочаровывающая вещь о Swift, которую я заметил. Почти все языки сценариев допускают многострочные строки.

C ++ 11 добавил необработанные строковые литералы, которые позволяют вам определять свой собственный терминатор

C # имеет свои @literals для многострочных строк.

Даже простой C и, следовательно, старомодный C ++ и Objective-C допускают конкатенацию, просто помещая несколько литералов рядом, поэтому кавычки свернуты. Пробелы не учитываются, когда вы делаете это, поэтому вы можете поместить их в разные строки (но нужно добавить свои собственные новые строки):

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

Поскольку swift не знает, что вы поместили текст в несколько строк, я должен исправить пример Коннора, точно так же, как мой пример C, явно указав новую строку:

var text:String = "This is some text \n" +
                  "over multiple lines"
Энди Дент
источник
4
Я уверен, что в этом есть ограничения. Я попытался разбить строку на 13 строк (это многострочный информационный текст). Он не только не смог завершить компиляцию, но и поставил мой Mac на колени. Как я уже сказал, я не могу категорически сказать, что это проблема, но будьте осторожны, последствия довольно плохие.
Дерек Найт
Я разбился несколько раз, даже до компиляции. Я думаю, что процесс «SourceKitService», который отвечает за выделение синтаксиса и завершение кода (я полагаю), также ответственен за эти сбои.
Павел Бревчински
@DerekKnight Это ошибка компилятора, а не ограничение языка. Если это все еще сохраняется, вы должны подать радар.
radex
@bluesm FYI: SourceKit - это отдельный процесс, поэтому он не может привести к сбою Xcode. Он делает подсветку синтаксиса и завершение кода, правильно, но на данный момент сама компиляция живет в процессе Xcode - вот почему ошибка компилятора иногда
приводит к самому удалению
17

Начиная с Swift 4.0 возможны многострочные строки, но есть несколько правил:

  1. Вам нужно начинать и заканчивать свои строки тремя двойными кавычками, """ .
  2. Содержание вашей строки должно начинаться с отдельной строки.
  3. Завершение """также должно начинаться с отдельной строки.

Кроме этого, вы готовы идти! Вот пример:

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

Посмотрите, что нового в Swift 4 для получения дополнительной информации.

TwoStraws
источник
К сожалению, это не работает в Xcode 8.3.3 Playground. Я получаю ошибку "неопределенная строка".
Джеймс Фостер
Как я уже сказал, эта функция является новой в Swift 4 - либо установите набор инструментов Swift 4 в Xcode 8.3.3, либо установите Xcode 9.
TwoStraws
16

Как указывает litso, повторное использование +оператора -Operator в одном выражении может привести к зависанию бета-версии XCode (только что проверено с помощью бета-версии XCode 6): бета-версия Xcode 6 не компилируется

Альтернативой многострочным строкам на данный момент является использование массива строк и reduceего с +:

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

Или, возможно, проще, используя join:

var text = "".join(["This is some text ",
                    "over multiple lines"])
Джонас Рейнш
источник
Уменьшенная версия у меня работала на бета 6, но объединение бросило исключение.
Тристан Уорнер-Смит
9

Swift 4 решил эту проблему, предоставив поддержку строкового литерала в несколько строк. Чтобы начать строковый литерал, добавьте три двойных кавычки (”” ”) и нажмите клавишу возврата. После нажатия клавиши возврата начните писать строки с любыми переменными, разрывами строк и двойными кавычками. как бы вы написали в блокноте или любом текстовом редакторе. Чтобы завершить многострочный строковый литерал, снова напишите (”” ”) в новой строке.

Смотрите ниже пример

     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 - правильный ответ, но если вы хотите добавить строки в оператор печати, то, что вы ищете, \nи / или \rони называются Escape-последовательности или Escape-символы, это ссылка на документацию Apple по этой теме.,

Пример:

print("First line\nSecond Line\rThirdLine...")
Хуан Боэро
источник
6
Это не то, что кто-то хочет. Мы хотим иметь возможность иметь перенос строк в исходном коде для строковых литералов, а не (обязательно) разрывы строк в отображаемом выводе . Это было довольно ясно в первоначальном вопросе, я думаю. Люди с положительными оценками явно поняли. Люди с отрицательными оценками, очевидно, нет.
ArtOfWarfare
5
@ArtOfWarfare - это ответ, который я искал, и эта страница была лучшим результатом при поиске «новой строки быстрой строки». Очевидно, это не так очевидно, как вы говорите.
Джон Р Перри
4

Добавление к ответу @Connor также должно быть \ n. Вот пересмотренный код:

var text:String = "This is some text \n" +
                  "over multiple lines"
Пандуранг Яхвад
источник
3

В следующем примере показано многострочное продолжение с использованием круглых скобок в качестве простого обходного пути для ошибки Swift начиная с бета-версии Xcode 6.2, где он жалуется, что выражение слишком сложное, чтобы его можно было разрешить за разумное количество времени, и рассмотреть возможность разбивки его на меньшие куски:

    .
    .
    .
    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)
    .
    .
    .
ClearLight
источник
0

Другой способ, если вы хотите использовать строковую переменную с некоторым предопределенным текстом,

var textFieldData:String = "John"
myTextField.text = NSString(format: "Hello User, \n %@",textFieldData) as String
myTextField.numberOfLines = 0
Zoran777
источник
0

Вы можете использовать Unicode Equals для ввода или \nи реализовать их внутри вашей строки. Например: \u{0085}.

Hooman
источник
0

Образец

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

В случае, если вы не нашли подходящий оператор +

Даниэль Коэн
источник
0

Один из подходов состоит в том, чтобы установить текст метки на attribuText и обновить строковую переменную, чтобы включить HTML для переноса строки (<br /> ).

Например:

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

Вывод:

This is some text
over multiple lines

Надеюсь это поможет!

B-Rad
источник
Вы не можете присвоить Stringзначение (текст) NSAttributedString?свойству (label.attributedText).
Максим Ашуров
0

Вот фрагмент кода для разделения строки на n символов, разделенных на строки:

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

Я пробовал несколько способов, но нашел еще лучшее решение: просто используйте элемент «Просмотр текста». Это текст показывает несколько строк автоматически! Найдено здесь: UITextField несколько строк

Оливер Райс
источник
(просто вы знаете, что отрицательные отзывы, вероятно, связаны с тем, что вопрос был о форматировании в коде, а не в пользовательском интерфейсе… и предоставление примера кода в вашем ответе, вероятно, сделало бы это более очевидным)
benc