All right.
So welcome to the Swift Deep Dive on loops. And loops are really important constructs in programming
in general, not just in Swift.
So let's say that we have a scenario where you want a robot to, say, drop a coin on every single tile
and you want him to repeat this process so that he covers all of the tiles on the floor.
Now, you could write your code pretty much like this where you just tell it to move(1) putCoin, move
(1) putCoin.
But notice how many parts of our code is being repeated.
And while you could probably simplify this by putting move and put coin into its own function as we
learned previously, and then calling that function, but it's still quite repetitive. And what are we?
We're programmers, right?
And what does Bill Gates say?
Well, you will always choose a lazy person to do a difficult job because it will find an easy way to
do it.
So how can we be lazy?
How can we use programming and the computer to do all of these repetitive tasks instead of us having
to type it all out?
Well, this is where loops really come in handy. And the most common type of loop that you'll see is the
For In Loop.
So let's say that you've got an array of some names.
Say, these are the name of your contacts with your friends and you want to be able to print out each
of them in order. Because this is an array,
so an ordered sequence of elements,
we can simply write "for," and we create this entirely new constant in here.
So this name is a new constant that we've decided to call name, and then the "in" keyword is followed by
the actual sequence.
So in this case, it's our array up here.
So now when we go ahead and print each of the names with a "Hello," then what's going to happen is this
loop is going to run for as many times as there are elements in our array.
So in this case, it's one, two, three, four.
And once this code gets executed,
we'll see, "Hello, Anna!" and then, "Hello, Alex!"
"Hello, Brian! and "Hello, Jack!"
So it's looping through our array and it's performing some sort of action. In this case, just simply printing
out the name and the word "Hello,"
and it's doing this many, many times without us having to explicitly write
Hello,
name, square brackets, zero. Hello, name, square bracket 1, et cetera. So we can do this as long as we have a sequence
to work with.
Another way is working with a range,
right?
So we've seen the range operator and this, as you might remember, is a close-range operator.
So this is a range between 1 and 5 including both 1 and 5.
So in this case, we've created again another constant which is called number and this number is going
to be set to equal each value in this sequence for every time this loop gets run.
So if we decided to print out the number each time the loop is run, then what's going to happen is that
this number constant is first going to be equal to 1, the first time the loop runs, and then this entire
block gets executed,
and we should get the words "Hello 1" printed. And then the next time number runs,
it's now equal to the next value in the range,
so it'll be 2, and so on and so forth.
So we'll get this looping effect running a total of five times because our range goes from 1 all the
way up to and including 5.
Now, if you didn't actually need to use the value of the numbers in the range, then you can simply bypass
it by adding just a underscore. So we could turn our code to look something like this. Because we don't
need that number anymore,
we just wanted, say, for example, the word "Hello" printed out five times, then we could change our for loop
to look something like this.
And now it's going to do what we asked to print the words "Hello" from 1 to 5,
so a total of five times. And we're basically just getting on loop to run for a specified number of times
without using any of the values inside this sequence that we've provided here. Coming back to our original
example where we had our little robot to simplify things. Let's say that we only wanted to put it along
this one horizontal line, right, where it's very much "move (1) putCoin, move (1) putCoin. And this is
the code that we would have had to write if we weren't using loops. But by simply using a loop, we can
get putCoin, move (1) to be repeated five times. And, again, in this case, we're not using any of the values
in our sequence here,
so we've put an underscore here, instead of a name for a constant.
So, now let's take a look at this in our playgrounds and see it in action.
Here I've got five types of sequences.
I've got an array of fruits. I've got a dictionary of contacts and their phone numbers.
I've got a string. I've got a halfOpenRange which has that less than symbol at the end. And also
a closRange, which you saw earlier, which just has the three dots.
So, now I can create a for loop.
So as soon as I starts writing "for," you can see that Xcode gives me that code snippet of a "for" statement
and you can see that we have three parts which we need to fill and the rest are keywords, the "for" and the "in."
So, for item in items. The easiest one is, of course, fruit, right?
This is the singular of the fruits plural.
This is the name that I'm giving a constant which is going to be assigned to each element inside my
fruits array.
So my fruit array goes after the key word.
And now as for my code, I'm just going to simply print out each fruit.
So notice how this is an array of strings,
but this is simply just a string. For every single time this for loop runs,
this constant fruit will get assigned a value depending on where we are in this sequence.
So, now if I run this code, you'll see that it prints out each of the items in order.
Now, this is how arrays work.
They are ordered sequences. But a close relative of the array is something called a Set. And a set is
simply a more efficient type of collection that allows you to put in many, many items, such as what we've
got here,
but it does not guarantee the order of those items.
So that means that if I now try and print fruit in fruits, you'll see that I won't get the original order
that I put it in like I did with the array where I'm guaranteed that it's going to execute it in the
order that I created the array. Once it turns into a set,
it's just going to do it in the most efficient way possible and it's going to print down all the items
in there, and it's going to loop through all of them
but it's not guaranteeing any sort of particular order.
So in certain cases, you might value the efficiency more than the order, in which case you would use a
set data type,
and other times, you really care about the order of the elements that went into that sequence, in which
case you would use an array instead.
The next thing is we've got a dictionary here,
right?
And we can do exactly the same thing.
We can say, for person in our contacts, we're going to print the person's key.
So notice how dictionaries are composed of key value pairs, right?
Each item that goes in there has a key and a value.
So if we loop through our contacts and every time this loop runs, we turn each of these items into a
constant code person, and then we print person.key, we're going to get basically all of the names
that's in our dictionary. And if we print person.value instead, we're going to instead get all of the
values that are inside our contacts.
Now, as you saw earlier in the previous lesson, we can do the same with string.
So if we loop through each letter in our word "supercalifragilisticexpialidocious" and we print
each of these letters, and go ahead and run our code, then you'll see that it actually takes each and
every single letter of that string and print it out individually.
So in total, our loop actually run a total of 34 times because there's 34 characters in this gigantic
word.
Now, as you saw in the slides earlier, we can use again the "for number in," say, our halfOpenRange and
print the number,
so now if we hit run, you'll see that it prints 1, 2, 3, 4, up to, but not including 5, because
of this, the less than symbol, which turns it into a halfOpenRange.
But instead if we use the closedRange operator which is just the three dots, then you'll see it prints
1,2, 3, 4, including 5.
So it runs the loop a total of five times in this case.
And in this case, it runs it a total of four times.
So if we wanted to simply just get it to run a particular block of code a number of times, then we can
replace this constant with an underscore, which is the same as kind of saying like let, underscore, equal,
I don't know,
1 to 5,
right?
This is basically exactly the same thing.
It just means that we're not gonna be using this constant anywhere within our code.
So, now we can't print no because it doesn't exist anymore, but we can print something else. We can print
"Loop is running." And now when I hit run, you'll see that in the halfOpenRange, it runs four times.
So my block of code inside here is going to run four times as well. Now, another related type of loop
is something called a While Loop. And while loops work where you have a "while" keyword, and then you have
something that is tested, a condition, right?
And if this condition say, I don't know," 8 is greater than five, or the sky is equal to blue,
if that is true, then this entire loop is going to continuously run until this condition becomes false.
As you can imagine, this can be dangerous if you expected something to turn false at some point, but it
actually never does. Say, you expected, I don't know, the user to type a particular letter, "A," but they never
type the letter "A,"
well, then in that case, your while loop is going to run until forever which is called an infinite loop.
And if you search for one infinite loop in maps, what you'll discover is actually Apple's headquarters.
So right here. This is how we programmers try to be funny by building large buildings representing concepts
in programming.
Going back to our playground, let's say that I wanted to create a while loop instead,
right?
So I start out with the "while" keyword and, again, Swift has a code snippet for that as well.
And then, I'll have to supply a condition, in this case what I'm going to test is I want my while loop
to run for a single second, so I can get hold of the current time right now by creating a variable code "now"
by setting equal to Date.timeIntervalSince1970, and it's not going to recognize a date because
I need to import the Foundation module in order to tell it about this Date object which is a single point
in time. And the timeIntervalSince1970 is going to give me the number of seconds since 0 o' clock on
January 1,1970.
So this is a standard in Unix time.
And what this means is that this now is going to be equal to the number of seconds since January 1,
1971.
I'm gonna create a constant code oneSecondFromNow and this is simply just going to equal to
now + 1 second.
Now, remember, this "now" is actually going to be equal to the value of the time when I run this code
when line 13 gets executed. And then immediately, I'm going to add one second to it and I'm going
to have a value of the number of seconds since 1970, January 1st, plus one second. And in my while condition,
what I'm going to test is I'm going to say if now happens to be less than oneSecondFromNow,
so as in one second has yet to pass,
this is what that condition tests,
well then I'm gonna go ahead and print "waiting..."
There's one last thing that I have to do which is inside my while loop,
I have to keep updating this now to equal the current exact time.
So that means that, initially, this gets set to a value which is used to specify 1 second from now, and
then I keep updating the clock to the current value of the clock and print "waiting..."
until now is no longer less than 1 second from now.
So I'll go ahead and comment out my for loop, and then run this. You'll see that it's gonna take a little
bit of time because it's actually going to run this code quite a few times, in fact,
3,974 times, and it printed "out waiting..."
that many times.
So this is an indication of just how fast these loops can actually run.
Now, the reason why I say while loops are notoriously dangerous is because you have to make sure that
this condition never ends up being continuously true until the end of time. Say, instead of checking while
now is less than oneSecondFromNow, in which case it will actually stop after a second. If I instead
checked a condition where it's always going to be true, say, 3 is greater than 2, until the end of
time, 3 is still going to be greater than 2.
Don't do this because your computer will actually crash. But I'm going to run it on my computer, just
so you can see what happens.
So when I hit run, you're going to see that it's going to continuously go many, many times and it's not
really going to stop until the Mac realizes, well, actually this process has been going on for a long
time and I probably should interrupt it.
And in fact, even if you tried to stop the playground, it's actually not really going to stop your code
because it's already running in the background.Aand at some point, Xcode actually just crashes.
So while loops can generate these infinite loops, so you have to be really careful when you're working
with them and ensure that the condition is clearly one that can turn false at one point. And the reason
why you would use a while loop is because you have a certain condition that you know is eventually going
to turn from true to false, but you don't know exactly when.
So it could be something that is an unknown,
say, I don't know how long it'll take for a particular image load from the internet,
well, then maybe the while loop is something you could use. But I recommend trying to use the for loop,
instead of the while loop at least when you're starting out, when you're unfamiliar with it, because it's
a notorious source of bugs, and can generate these infinite loops of which mine is still going on,
by the way, even if I try to tell it to stop. So after this lesson, I recommend having a read of the Swift
Book on control flow and that's going to include For-In Loops as well as While Loops that we talked
about.
So just get a little bit more background on that. And then we'll head back and continue building out
our app.