Some of the most basic operations in Swift, and any programming language, involve manipulating text and numbers, and determining true/false answers.
Strings, Ints, Floats, and Bools
Getting ready
Let's take a look at the basic types in Swift that enable us to perform these operations. As we do that, we will learn how to assign constants and variables, and touch on Swift's static typing and mutability system.
How to do it...
Let's execute some Swift code that explores the basic types, and then we can walk through it step by step:
- Type the following into a new Playground file:
let phrase: String = "The quick brown fox jumps over the lazy dog"
let numberOfFoxes: Int = 1
let numberOfAnimals: Int = 2
let averageCharactersPerWord: Float = (3+5+5+3+5+4+3+4+3) / 9
print(averageCharactersPerWord) // 43
/*
phrase = "The quick brown ? jumps over the lazy ?" // Doesn't compile
*/
var anotherPhrase = phrase
anotherPhrase = "The quick brown jumps over the lazy "
print(phrase) // "The quick brown fox jumps over the lazy dog"
print(anotherPhrase) // "The quick brown jumps over the lazy "
var phraseInfo = "The phrase" + " has: "
print(phraseInfo) // "The phrase has: "
phraseInfo = phraseInfo + "\(numberOfFoxes) fox and \(numberOfAnimals) animals"
print(phraseInfo) // "The phrase has: 1 fox and 2 animals"
print("Number of characters in phrase: \(phrase.count)")
let multilineExplanation = """
Why is the following phrase often used?
"The quick brown fox jumps over the lazy dog"
This phrase contains every letter in the alphabet.
"""
let phrasesAreEqual = phrase == anotherPhrase
print(phrasesAreEqual) // false
let phraseHas43Characters = phrase.count == 40 + 3
print(phraseHas43Characters) // true
- Execute the playground to verify that it compiles and runs without any errors. Your playground should look like the following screenshot, with an output for each line in the timeline on the right-hand side and printed values in the console at the bottom:
How it works...
Let's step through the preceding code line by line to understand it:
let phrase: String = "The quick brown fox jumps over the lazy dog"
We designate that we want to assign a constant by using the let keyword, and we give that constant a name--phrase. After the :, we define the type of constant we want to assign; in this case, we want to assign a String (String is how most programming languages refer to text). The = sign indicates that we are assigning a value to the constant we have defined, and The quick brown fox jumps over the lazy dog is a String literal, which means that it's an easy way to construct a string. So, we are assigning the String literal on the right-hand side of the = sign to the constant on the left-hand side of the = sign:
let numberOfFoxes: Int = 1
let numberOfAnimals: Int = 2
Now, we will assign some more constants, but this time they are Int, or integers:
let averageCharactersPerWord: Float = (3+5+5+3+5+4+3+4+3) / 9
Rather than assigning a value directly, we can assign the outcome from a mathematical expression to the constant. This constant is a Float or floating point number; in other words, it can store fractions rather than integers:
print(averageCharactersPerWord)
The print function allows us to see the output from any expression printed to the console or displayed in the playground. The playground has displayed the output of the statement as 3.88889. The actual value of the mathematical expression we performed is 3.88888888... with an infinite number of 8s. However, the print function has rounded this up to just five decimal places. This potential difference between the true value of a floating point number and how it's represented by the Swift language is important to remember when dealing with floats:
phrase = "The quick brown ? jumps over the lazy ?" // Doesn't compile
The playground doesn't produce an output for this line because it is commented out. The /* syntax before the line and the */ syntax after the line denote that this is a comment block, so the Swift compiler should ignore anything typed in this block.
Remove /* and */ (you'll see that // Doesn't compile is still highlighted in green; this is because // denotes that anything after this, on the same line, is also a comment); now try and run the code. The code cannot run because the compiler has detected a problem with this line, so let's look at the line to determine the issue.
On the left-hand side of the = sign, we have phrase, which we declared earlier, and now we are trying to assign a new value to it. We can't do this because we defined phrase as a constant using the let keyword. We should only use let for things we know will not change. If we want to define something that can change, we declare it as a variable using the var keyword:
var anotherPhrase = phrase
Here, we take our constant phrase and assign it to the anotherPhrase variable. This ability to define something as unchanging, or immutable, is an important concept in Swift, and we will revisit in the later chapters:
anotherPhrase = "The quick brown jumps over the lazy "
Since anotherPhrase is a variable, we can assign a new value to it. Strings in Swift are fully Unicode compliant, so we can have some fun and use emojis instead of words:
print(phrase) // "The quick brown fox jumps over the lazy dog"
print(anotherPhrase) // "The quick brown jumps over the lazy "
In the preceding lines, we have done the following:
- Defined a string called phrase
- Defined a string called anotherPhrase as having the same value as phrase
- Changed the value of anotherPhrase
- Printed the value of phrase and anotherPhrase
When we do this, we see that only anotherPhrase prints the new value that was assigned, even though the values of phrase and anotherPhrase were initially the same. Although phrase and anotherPhrase had the same value, they do not have an intrinsic connection; so, when anotherPhrase is assigned a new value, this does not affect phrase.
Strings can be easily combined using the + operator; this gives the expected result:
var phraseInfo = "The phrase" + " has: "
print(phraseInfo) // "The phrase has: "
You will often want to create strings by including values derived from other expressions. We can do this with String interpolation. The values inserted after \( and before ) can be anything that can be represented as a string, including other Strings, Ints, Floats, or expressions:
phraseInfo = phraseInfo + "\(numberOfFoxes) fox and \(numberOfAnimals) animals"
print(phraseInfo) // "The phrase has: 1 fox and 2 animals"
Multiline string literals can be defined using """ at the beginning and end of the string. The contents of the multiline string must be on a separate line from the start and end signifiers; there is no need to escape and use " within the string as you would need to do in a single-line string:
let multilineExplanation = """
Why is the following phrase often used?
"The quick brown fox jumps over the lazy dog"
This phrase contains every letter in the alphabet.
"""
Strings in Swift are collections, which are containers of elements; in this case, a string is a collection of characters. We will cover collections in more depth in a later recipe, but for now, it's enough to know that your collections can tell you how many elements they contain through their count property. We use this to output the number of characters in the phrase:
print("Number of characters in phrase: \(phrase.count)")
Boolean values represent either true or false. Here, we are assigning the result of the phrase == anotherPhrase equality expression to the phrasesAreEqual constant. The == operator compares the values on the left- and right-hand side of the operator:
let phrasesAreEqual: Bool = phrase == anotherPhrase
print(phrasesAreEqual) // false
As we discussed earlier, although we assigned anotherPhrase the value of phrase initially, we then assigned a new, different value to anotherPhrase; therefore, phrase does not equal anotherPhrase, and the expression assigns the Boolean value of false:
let phraseHas43Characters: Bool = phrase.characters.count == 40 + 3
print(phraseHas43Characters) // true
Each side of the == operator can be any expression that evaluates to match the type of the other side. In this case, the character count of phrase equals 43, so the constant is assigned the value of true.
There's more...
While we defined constants and variables earlier, we also defined the type of thing we are assigning to explicitly. For example, consider the following:
let clearlyAString: String = "This is a string literal"
Swift is a statically typed language, which means any constant or variable that we define has to have a specific type, which cannot be changed. However, in the preceding line, the clearlyAString constant is clearly a String! The right-hand side of the expression is a String literal, and therefore we know that the left-hand side will be a String. More importantly, the compiler also knows this. Swift is all about being concise, so since the type can be inferred by the compiler, we do not need to explicitly state it. Try the following instead, and see whether you can run the code:
let clearlyAString = "This is a string literal"
In fact, all the type declaration that we have made so far can be removed! So, go back through the code we have already written and remove all type declarations (:String, :Int, :Float, and :Bool), as they can all be inferred.
See also
Further information about these base types in Swift can be found in Apple's documentation of the Swift language:
- Ints, Floats, and Bools:
http://swiftbook.link/docs/the-basics
- Strings and characters: