Day 01
Day 01 êŽë š
First steps in Swift
SwiftUI is a powerful framework for building user-interactive apps for iOS, macOS, tvOS, and even watchOS. But you canât build software without having a programming language, so behind SwiftUI lies Swift itself: a powerful, flexible, and modern programming language that youâll use for all your SwiftUI apps.
As Mark Twain once said, âthe secret to getting ahead is getting started.â Well, youâre starting now, so weâre going to dive in and learn about variables, constants, and simple data types in Swift.
Today you have seven tutorials to complete. If you want to dive deeper into each topic there is optional further reading, but you donât need to read that unless you want to and have the time. Regardless, there are a number of short tests to help make sure youâve understood key concepts.
I know, I know: the temptation is strong to continue on to watch more videos and take more tests beyond those linked below, but remember: donât rush ahead! Itâs much better to do one hour a day every day than do chunks with large gaps between.
1. Introduction: Why Swift?
1. Introduction: Why Swift?
There are lots of programming languages out there, but I think youâre going to really enjoy learning Swift. This is partly for practical reasons â you can make a lot of money on the App Store! â but there are lots of technical reasons too.
You see, Swift is a relatively young language, having launched only in 2014. This means it doesnât have a lot of the language cruft that old languages can suffer from, and usually means there is only one way to solve a particular problem.
At the same time, being such a new programming language means that Swift leverages all sorts of new ideas built upon the successes â and sometimes mistakes â of older languages. For example, it makes it hard to accidentally write unsafe code, it makes it very easy to write code that is clear and understandable, and it supports all the world languages so youâll never see those strange character errors that plague other languages.
Swift itself is just the language, and isnât designed to draw anything on the screen. When it comes to building software with Swift, youâll be using SwiftUI: Appleâs powerful framework that creates text, buttons, images, user interaction, and much more. As the name suggests, SwiftUI was built for Swift â itâs literally designed to leverage the power and safety offered by the language, which makes it remarkably quick to build really powerful apps.
So, you should learn Swift because you can make a lot of money with it, but also because it does so many things really well. No cruft, no confusion, just lots of power at your fingertips. Whatâs not to like?
2. Introduction: About this course
2. Introduction: About this course
Iâve been teaching folks to write Swift since 2014, the same year Swift launched, and at this point Hacking with Swift is the worldâs largest site dedicated to teaching Swift.
Along the way I learned a huge amount about what topics matter the most, how to structure topics into a smooth and consistent flow, and most importantly how to help learners remember topics theyâve learned. This course is the product of all that learning.
Unlike my previous work this does not strive to teach you every aspect of Swift, but instead it spends more time on the subset of features that matter the most â the ones youâll use in every app you build, time and time again. Yes, there are some advanced language features covered, but Iâve cherrypicked them based on usefulness. When youâve finished the book you might want to carry on learning some of the more advanced features, but I suspect youâd much rather get busy learning how to use SwiftUI.
Each chapter of this book is available as both text and video, but they cover exactly the same material so youâre welcome to learn whichever way suits you best. If youâre using the videos youâll notice that I sometimes introduce topics using slides and sometimes demonstrate them in Xcode. It might feel repetitive, but itâs intentional â thereâs a lot of things to learn, and if you saw each one only once it just wouldnât stay in your memory!
Thereâs one last thing: you might notice how many chapters start with âHow toâŠâ, and thatâs intentional â this book is here to show you how to do things in a hands-on way, as opposed to delving into theory. Theory is important, and youâll come across a lot of it as you can continue to learn, but here the focus is relentlessly practical because I believe the best way to learn something new is to try it yourself.
Programming is an art: don't spend all your time sharpening your pencil when you should be drawing.
3. Introduction: How to follow along
3. Introduction: How to follow along
Thereâs a lot of code shown off in this book, and I really want to encourage you to try it all yourself â type the code into your computer, run it and see the output, then experiment a little to make sure you understand it.
To run the code in this book you should have installed Xcode 13.0 or later from the Mac App Store. Itâs free, and includes everything you need to follow along.
Weâll be using a Swift Playground for all the code in this book. You can create one by launching Xcode, then going to the File menu and choosing New > Playground. When youâre asked what kind of playground to create, choose Blank from the macOS tab, then save it somewhere you can get to easily.
Playgrounds are like little sandboxes where you can try out Swift code easily, seeing the result of your work side by side with the code. You can use one playground for all the work youâll be doing, or create new a playground for each chapter â do whatever works best for you.
Tip: The first time you run code in a playground it might take a few seconds to start, but subsequent runs will be fast.
4. How to create variables and constants
4. How to create variables and constants
Whenever you build programs, youâre going to want to store some data. Maybe itâs the userâs name they just typed in, maybe itâs some news stories you downloaded from the internet, or maybe itâs the result of a complex calculation you just performed.
Swift gives us two ways of storing data, depending on whether you want the data to change over time. The first option is automatically used when you create a new playground, because it will contain this line:
var greeting = "Hello, playground"
That creates a new variable called greeting
, and because itâs a variable its value can vary â it can change as our program runs.
Tip: The other line in a macOS playground is import Cocoa
, which brings in a huge collection of code provided by Apple to make app building easier. This includes lots of important functionality, so please donât delete it.
There are really four pieces of syntax in there:
- The
var
keyword means âcreate a new variableâ; it saves a little typing. - Weâre calling our variable
greeting
. You can call your variable anything you want, but most of the time youâll want to make it descriptive. - The equals sign assigns a value to our variable. You donât need to have those spaces on either side of the equals sign if you donât want to, but itâs the most common style.
- The value weâre assigning is the text âHello, playgroundâ. Notice that text is written inside double quotes, so that Swift can see where the text starts and where it ends.
If youâve used other languages, you might have noticed that our code doesnât need a semicolon at the end of the line. Swift does allow semicolons, but they are very rare â youâll only ever need them if you want to write two pieces of code on the same line for some reason.
When you make a variable, you can change it over time:
var name = "Ted"
name = "Rebecca"
name = "Keeley"
That creates a new variable called name
, and gives it the value âTedâ. It then gets changed twice, first to âRebeccaâ and then to âKeeleyâ â we donât use var
again because we are modifying an existing variable rather than creating a new one. You can change variables as much as you need to, and the old value is discarded each time.
(Youâre welcome to put different text in your variables, but Iâm a big fan of the TV show Ted Lasso so I went with Ted. And yes, you can expect other Ted Lasso references and more in the following chapters.)
If you donât ever want to change a value, you need to use a constant instead. Creating a constant works almost identically to creating a variable, except we use let
rather than var
, like this:
let character = "Daphne"
Now, when we use let
we make a constant, which is a value that canât change. Swift literally wonât let us, and will show a big error if we try.
Donât believe me? Try putting this into Xcode:
let character = "Daphne"
character = "Eloise"
character = "Francesca"
Again, there are no let
keywords in those second and third lines because we arenât creating new constants, weâre just trying to change the one we already have. However, like I said that wonât work â you canât change a constant, otherwise it wouldnât be constant!
If you were curious, âletâ comes from the mathematics world, where they say things like âlet x be equal to 5.â
Important: Please delete the two lines of code that are showing errors â you really canât change constants!
When youâre learning Swift, you can ask Xcode to print out the value of any variable. You wonât use this much in real apps because users canât see whatâs printed, but itâs really helpful as a simple way of seeing whatâs inside your data.
For example, we could print out the value of a variable each time itâs set â try entering this into your playground:
var playerName = "Roy"
print(playerName)
playerName = "Dani"
print(playerName)
playerName = "Sam"
print(playerName)
Tip: You can run code in your Xcode playground by clicking the blue play icon to the left of it. If you move up or down along that blue strip, youâll see the play icon moves too â this lets you run the code up to a certain point if you want, but most of the time here youâll want to run up to the last line.
You might have noticed that I named my variable playerName
, and not playername
, player_name
, or some other alternative. This is a choice: Swift doesnât really care what you name your constants and variables, as long as you refer to them the same way everywhere. So, I canât use playerName
first then playername
later â Swift sees those two as being different names.
Although Swift doesnât care how we name our data, the naming style Iâm using is the standard among Swift developers â what we call a convention. If youâre curious, the style is called âcamel caseâ, because the second and subsequent words in a name start with a little bump for the capital letter:
let managerName = "Michael Scott"
let dogBreed = "Samoyed"
let meaningOfLife = "How many roads must a man walk down?"
If you can, prefer to use constants rather than variables â not only does it give Swift the chance to optimize your code a little better, but it also allows Swift to make sure you never change a constantâs value by accident.
4. How to create variables and constants - Additional
- Optional: Why does Swift have variables?
- Optional: Why does Swift have constants as well as variables?
- Test: Variables
- Test: Constants
5. How to create strings
5. How to create strings
When you assign text to a constant or variable, we call that a string â think of a bunch of Scrabble tiles threaded onto a string to make a word.
Swiftâs strings start and end with double quotes, but what you put inside those quotes is down to you. You can use short pieces of alphabetic text, like this:
let actor = "Denzel Washington"
You can use punctuation, emoji and other characters, like this:
let filename = "paris.jpg"
let result = "âïž You win! âïž"
And you can even use other double quotes inside your string, as long as youâre careful to put a backslash before them so that Swift understands they are inside the string rather than ending the string:
let quote = "Then he tapped a sign saying \"Believe\" and walked away."
Donât worry â if you miss off the backslash, Swift will be sure to shout loudly that your code isnât quite right.
There is no realistic limit to the length of your strings, meaning that you could use a string to store something very long such as the complete works of Shakespeare. However, what youâll find is that Swift doesnât like line breaks in its strings. So, this kind of code isnât allowed:
let movie = "A day in
the life of an
Apple engineer"
That doesnât mean you canât create strings across multiple lines, just that Swift needs you to treat them specially: rather than one set of quotes on either side of your string, you use three, like this:
let movie = """
A day in
the life of an
Apple engineer
"""
These multi-line strings arenât used terribly often, but at least you can see how itâs done: the triple quotes at the start and end are on their own line, with your string in between.
Once youâve created your string, youâll find that Swift gives us some useful functionality to work with its contents. Youâll learn more about this functionality over time, but I want to introduce you to three things here.
First, you can read the length of a string by writing .count
after the name of the variable or constant:
print(actor.count)
Because actor
has the text âDenzel Washingtonâ, that will print 17 â one for each letter in the name, plus the space in the middle.
You donât need to print the length of a string directly if you donât want to â you can assign it to another constant, like this:
let nameLength = actor.count
print(nameLength)
The second useful piece of functionality is uppercased()
, which sends back the same string except every one of its letter is uppercased:
print(result.uppercased())
Yes, the open and close parentheses are needed here but arenât needed with count
. The reason for this will become clearer as you learn, but at this early stage in your Swift learning the distinction is best explained like this: if youâre asking Swift to read some data you donât need the parentheses, but if youâre asking Swift to do some work you do. Thatâs not wholly true as youâll learn later, but itâs enough to get you moving forward for now.
The last piece of helpful string functionality is called hasPrefix()
, and lets us know whether a string starts with some letters of our choosing:
print(movie.hasPrefix("A day"))
Thereâs also a hasSuffix()
counterpart, which checks whether a string ends with some text:
print(filename.hasSuffix(".jpg"))
Important: Strings are case-sensitive in Swift, which means using filename.hasSuffix(".JPG")
will return false because the letters in the string are lowercase.
Strings are really powerful in Swift, and weâve only really scratched the surface of what they can do!
5. How to create strings - Additional
- Optional: Why does Swift need multi-line strings?
- Test: Multi-line strings
6. How to store whole numbers
6. How to store whole numbers
When youâre working with whole numbers such as 3, 5, 50, or 5 million, youâre working with what Swift calls integers, or Int
for short â âintegerâ is originally a Latin word meaning âwholeâ, if you were curious.
Making a new integer works just like making a string: use let
or var
depending on whether you want a constant or variable, provide a name, then give it a value. For example, we could create a score
constant like this:
let score = 10
Integers can be really big â past billions, past trillions, past quadrillions, and well into quintillions, but they they can be really small too â they can hold negative numbers up to quintillions.
When youâre writing out numbers by hand, it can be hard to see quite whatâs going on. For example, what number is this?
let reallyBig = 100000000
If we were writing that out by hand weâd probably write â100,000,000â at which point itâs clear that the number is 100 million. Swift has something similar: you can use underscores, _
, to break up numbers however you want.
So, we could change our previous code to this:
let reallyBig = 100_000_000
Swift doesnât actually care about the underscores, so if you wanted you could write this instead:
let reallyBig = 1_00__00___00____00
The end result is the same: reallyBig
gets set to an integer with the value of 100,000,000.
Of course, you can also create integers from other integers, using the kinds of arithmetic operators that you learned at school: +
for addition, -
for subtraction, *
for multiplication, and /
for division.
For example:
let lowerScore = score - 2
let higherScore = score + 10
let doubledScore = score * 2
let squaredScore = score * score
let halvedScore = score / 2
print(score)
Rather than making new constants each time, Swift has some special operations that adjust an integer somehow and assigns the result back to the original number.
For example, this creates a counter
variable equal to 10, then adds 5 more to it:
var counter = 10
counter = counter + 5
Rather than writing counter = counter + 5
, you can use the shorthand operator +=
, which adds a number directly to the integer in question:
counter += 5
print(counter)
That does exactly the same thing, just with less typing. We call these compound assignment operators, and they come in other forms:
counter *= 2
print(counter)
counter -= 10
print(counter)
counter /= 2
print(counter)
Before weâre done with integers, I want to mention one last thing: like strings, integers have some useful functionality attached. For example, you can call isMultiple(of:)
on an integer to find out whether itâs a multiple of another integer.
So, we could ask whether 120 is a multiple of three like this:
let number = 120
print(number.isMultiple(of: 3))
Iâm calling isMultiple(of:)
on a constant there, but you can just use the number directly if you want:
print(120.isMultiple(of: 3))
6. How to store whole numbers - Additional
- Test: Strings and integers
7. How to store decimal numbers
7. How to store decimal numbers
When youâre working with decimal numbers such as 3.1, 5.56, or 3.141592654, youâre working with what Swift calls floating-point numbers. The name comes from the surprisingly complex way the numbers are stored by your computer: it tries to store very large numbers such as 123,456,789 in the same amount of space as very small numbers such as 0.0000000001, and the only way it can do that is by moving the decimal point around based on the size of the number.
This storage method causes decimal numbers to be notoriously problematic for programmers, and you can get a taste of this with just two lines of Swift code:
let number = 0.1 + 0.2
print(number)
When that runs it wonât print 0.3. Instead, it will print 0.30000000000000004 â that 0.3, then 15 zeroes, then a 4 because⊠well, like I said, itâs complex.
Iâll explain more why itâs complex in a moment, but first letâs focus on what matters.
First, when you create a floating-point number, Swift considers it to be a Double
. Thatâs short for âdouble-precision floating-point numberâ, which I realize is quite a strange name â the way weâve handled floating-point numbers has changed a lot over the years, and although Swift does a good job of simplifying this you might sometimes meet some older code that is more complex. In this case, it means Swift allocates twice the amount of storage as some older languages would do, meaning a Double
can store absolutely massive numbers.
Second, Swift considers decimals to be a wholly different type of data to integers, which means you canât mix them together. After all, integers are always 100% accurate, whereas decimals are not, so Swift wonât let you put the two of them together unless you specifically ask for it to happen.
In practice, this means you canât do things like adding an integer to a decimal, so this kind of code will produce an error:
let a = 1
let b = 2.0
let c = a + b
Yes, we can see that b
is really just the integer 2 masquerading as a decimal, but Swift still wonât allow that code to run. This is called type safety: Swift wonât let us mix different types of data by accident.
If you want that to happen you need to tell Swift explicitly that it should either treat the Double
inside b
as an Int
:
let c = a + Int(b)
Or treat the Int
inside a
as a Double
:
let c = Double(a) + b
Third, Swift decides whether you wanted to create a Double
or an Int
based on the number you provide â if thereâs a dot in there, you have a Double
, otherwise itâs an Int
. Yes, even if the numbers after the dot are 0.
So:
let double1 = 3.1
let double2 = 3131.3131
let double3 = 3.0
let int1 = 3
Combined with type safety, this means that once Swift has decided what data type a constant or variable holds, it must always hold that same data type. That means this code is fine:
var name = "Nicolas Cage"
name = "John Travolta"
But this kind of code is not:
var name = "Nicolas Cage"
name = 57
That tells Swift name
will store a string, but then it tries to put an integer in there instead.
Finally, decimal numbers have the same range of operators and compound assignment operators as integers:
var rating = 5.0
rating *= 2
Many older APIs use a slightly different way of storing decimal numbers, called CGFloat
. Fortunately, Swift lets us use regular Double
numbers everywhere a CGFloat
is expected, so although you will see CGFloat
appear from time to time you can just ignore it.
In case you were curious, the reason floating-point numbers are complex is because computers are trying to use binary to store complicated numbers. For example, if you divide 1 by 3 we know you get 1/3, but that canât be stored in binary so the system is designed to create very close approximations. Itâs extremely efficient, and the error is so small itâs usually irrelevant, but at least you know why Swift doesnât let us mix Int
and Double
by accident!
7. How to store decimal numbers - Additional
- Optional: Why does Swift need both Doubles and Integers?
- Optional: Why is Swift a type-safe language?
When youâre finished, donât forget to tell other people about your progress. Yes, this is only day one, but the more motivation you get now the more youâll be able to power through when things get tougher!
Reminder: I have a free iOS app that helps you practice Swift right on your iPhone and iPad. It contains alternative lessons that might help these new concepts sink in, plus lots more bonus activities. And did I mention it was free? Download it here.
Tips
- You can download Xcode from the Mac App Store by clicking here.
- As you progress in these early days youâll build up lots of code from each day. You can keep it in different playgrounds if you want, or you can delete it â itâs down to you.