With the release of Swift 4 next week and the implementation of proposal 168 now up and running in the Swift 4 toolchain I thought it would be nice to get in and get my hands dirty with multi-line string literals to provide some examples on how standard string manipulation practices now work with multi-line string literals in Swift 4. This tutorial will focus on some of the general operations developers use in working with and string manipulation for day to day tasks in development. For example, string creation, string interpolation, substring extraction, string mutation, and string equality.
NOTE: This tutorial assumes you have at least Swift 4.0 installed in your Xcode toolchain or that you are using a version of Xcode that supports Swift 4. To get started with this tutorial you can know a lot about Swift or a little about Swift, these examples are aimed at everyone.
1) Multi-Line String Literal Creation
In this first example I have created a very straight forward three line string literal. Notice the open and close three quotation delimiter on a separate line at the beginning and the end of the string. This is crucial to how the lexer in Swift notices that the string is a multi-line string and this syntax must be adhered to this in order to create a multi-line string. As of right now a multi-line string cannot be created with the content of the string on the same line as the the open or close delimiter. Meaning, the first character of the string has to be on a different line as the opening delimiter. This syntax rule also applies to the last character in the string and the closing delimiter.
Another item to note is the console output of the examples print statement:
Multi-Line String: Line One
Line Two
Line Three
Notice that the first line of the multi-line string is on the same line as the string from the print statement, while the second and third lines of the multi-line string are on new lines. That is because there is a newline (\n) character present after every line in the multi-line string literal and this newline character is not displayed in the output of the Xcode editor. So, the Swift lexer actually reads the string above as, "Line One\nLine Two\nLine Three," and then uses standard practices to parse the output and hide the newline characters.
// --- Multi-line string literal example --- let multiLineString = """ Line One Line Two Line Three """ print("Multi-Line String: \(multiLineString)")
2) Multi-Line String Literal Interpolation
In the second example for multi-line strings I wanted to create an example of string interpolation. String interpolation is the behavior of inserting values or data types into a string at a specific index so that when the string is displayed a string representation of that data type is presented in the output of the string. String interpolation is probably one of the most common behaviors we do with strings as iOS developers, so I wanted to provide an example of how this behavior works in the context of multi-line string literals.
You will probably notice if you are familiar with string interpolation already that in the example I have provided there is not much change from how string interpolation works in a single line string literal. This is really by design, and because I wanted to show off that this feature is now up and running in Swift 4! A couple of weeks ago this feature was not fully implemented yet and I was not sure it would be ready in time for the Swift 4 release at WWDC.
The print statement from the example provided will output the following:
Multi-Line String Template: Line: 1
Line: 2
Line: 3
Based upon the first example this is probably what you were expecting to see. Same behavior, each line contains a newline character and each line is presented that way by the output of the print statement.
// --- Multi-line string literal with interpolation --- var lineNumbers = [1, 2, 3] let multiLineTemplate = """ Line: \(lineNumbers[0]) Line: \(lineNumbers[1]) Line: \(lineNumbers[2]) """ print("\nMulti-Line String Template: \(multiLineTemplate)")
3) Multi-Line String Literal Mutation
In the third example of multi-line string literals we get into the fun stuff involving string mutation! The first example for string mutation explains how to cut a substring out of a multi-line string literal in the middle of the multi-line string. This example follows the best practices of creating a range with a starting and ending index and then takes advantage of the substring method to extract that substring and print it out for display. The output of the substring example below will be the following:
Second line: I really enjoy tutorials.
The next example of multi-line string mutation is on replacing a the occurrences of a character in a string with another character. In this example I am using the replacingOccurrences method to replace all whitespace with newline characters (\n). The output of the replace mutation will look something like this:
Replaced value string: Hello
AgnosticDev!
I
really
enjoy
tutorials.
Especially
Swift
Tutorials!
As you can see, multi-line string literals handle this behavior just like a standard one line string literal and all of the words that were present in the multi-line string are now on a new line.
// --- Multi-line string literal Mutation --- // Creating Substring var mutableMultiLineString = """ Hello AgnosticDev! I really enjoy tutorials. Especially Swift Tutorials! """ let startingIndex = mutableMultiLineString.index(mutableMultiLineString.startIndex, offsetBy: 19) let endingIndex = mutableMultiLineString.index(mutableMultiLineString.startIndex, offsetBy: 44) let range = startingIndex..<endingIndex let substring = mutableMultiLineString.substring(with: range) print("Second line: \(substring)") // Replacing Values let replacedString = mutableMultiLineString.replacingOccurrences(of: " ", with: "\n") print("Replaced value string: \(replacedString)")
4) Multi-Line String Literal Equality
In the fourth and last example I wanted to point out one key part of string equality that could trip up some conditional statements used in applications. First thing you will notice is that I created another multi-line string literal call nonEqualMultiLineString. This string is meant to contain the same content and spacing to almost identically match the mutableMultiLineString from example three, except for it is not the same under the hood. The following output of the this conditional statement will read:
No, these are not equal strings because of the missing newline, even though both strings have the same length.
Length of mutableMultiLineString: 72
Length of nonEqualMultiLineString: 72
As you can see the strings are not equal and this is the interesting point I wanted to bring up about multi-line string equality, in that, even though the strings contain the same content, and are the same length in character count, they are not considered to be equal strings by the compiler because of the missing newline character in the nonEqualMultiLineString variable. So make sure when checking for string equality, with multi-line strings, that you consider the newline character in as well because the strings may be of equal character length.
// --- Multi-line string literal Equality --- var mutableMultiLineString = """ Hello AgnosticDev! I really enjoy tutorials. Especially Swift Tutorials! """ let nonEqualMultiLineString = """ Hello AgnosticDev! I really enjoy tutorials. Especially Swift Tutorials! """ if mutableMultiLineString == nonEqualMultiLineString { print("Multi-line strings are equal!") } else { print("No, these are not equal strings because of the missing newline, even though both strings have the same length.") print("Length of mutableMultiLineString: \(mutableMultiLineString.characters.count)") print("Length of nonEqualMultiLineString: \(nonEqualMultiLineString.characters.count)") }
Now you know more about how to create and manipulate multi-line string literals! Please feel free to download the playground example from my Github and mess around with it. One thing to note again is that if your version of Xcode does not support Swift 4 yet, you will need to download the Swift 4 toolchain to run this playground in Xcode.
Thank you very much for reading!
Credits: Cover image designed by Freepik.
Comments
Xcode Playground?
When I try your first example in a Playground, I get the following error:
Playground execution failed: error: MyPlayground.playground:5:25: error: unterminated string literal
let multiLineString = """
Xcode Playground
James,
Thank you for trying out the code samples. On the playground you are executing, which Xcode toolchain are you using to run the playground, is it Xcode 8.0 or does it support Xcode 9.0?
Xcode 8.2.1 playground error
Hi Matt, I'm receiving the same error in Xcode 8.2.1 playground as James did with this example. Do I need Xcode 9 for this? Thanks