Creating Strings From Raw Text In Swift 5

Creating Swift strings from raw text can often be a pain. Properly escaping any quotes or backslash characters in the raw text is an exercise in frustration. Swift 5, shipping with Xcode 10.2, introduces a new syntax to make it easier to work with raw text.

Creating Strings With String Literals

When you create a String from literal text, you use the double quote (") as a starting and ending delimiter and the backslash (\) to escape special characters. For example, to create a String that preserves the double-quotes in this text:

let title1 = "Insert \"title\" here"
// Insert "title" here

Custom String Escaping (Swift 5)

In Swift 5, SE-0200 allows you to customize the delimiter and escape sequences. This is useful when working with raw text that might contain the delimiters or escape sequence.

You can pad the start, end and escape delimiters with one or more “#” characters. These three examples all produce the same result:

let title2 = #"Insert "title" here"#
let title3 = ##"Insert "title" here"##
let title4 = ###"Insert "title" here"###
// Insert "title" here

Note that we don’t need to escape the double-quotes now as they are no longer a delimiter. If our raw text contains our chosen delimiter we can pad with an extra “#”:

// raw text is "#Hello#"
// start delimiter is ##"
// end delimiter is "##
let regex1 = ##""#Hello#""##
// "#Hello#"

If we pad the delimiters with one or more #’s, we also need to pad the backslash escape sequence. For example, when interpolating a value:

let name = "Tom"
let greeting1 = "Hello \(name)"    // Hello Tom

When padding with a single # the escape sequence becomes \#:

let greeting2 = #"Hello \#(name)"# // Hello Tom

Custom delimiters become useful when we want to preserve escaped raw text. For example, when creating a String from some JSON. Using a multi-line String literal seems like a good approach:

let json1 = """
{
  "colors": ["red","green","blue"],
  "label": "Insert \"title\" here"
}
"""

The multi-line string literal is convenient when the text contains quotes, but it introduces an error in this case. The problem is that the compiler strips the backslash escaping around "title" resulting in some invalid JSON:

{
  "colors": ["red","green","blue"],
  "label": "Insert "title" here"
}

If we use a custom delimiter with multi-line string literals we can keep the escape sequence in the raw text:

let json2 = #"""
{
  "colors": ["red","green","blue"],
  "label": "Insert \"title\" here"
}
"""#

The resulting String with the preserved raw text (note the backslash-escaped double-quotes around title):

{
  "colors": ["red","green","blue"],
  "label": "Insert \"title\" here"
}

Further Reading