Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
Since our set up code is spread out across several functions, we want to get it all in one place. One way we can do that is to use an immediately executing anonymous function or closure. Let's check out how this works.
-
0:00
[MUSIC]
-
0:04
Before we move on to the next set of features and logic,
-
0:07
let's take a second to review our code.
-
0:10
When we first learned about building apps, I talked about refactoring.
-
0:14
Refactoring is the process of changing the structure of our code,
-
0:18
without changing any functionality.
-
0:21
We've got a bit of our functionality going in the app, but
-
0:24
already I think our view controller is becoming a bit unwieldy.
-
0:28
This is a good time to maybe improve our code.
-
0:31
I should note, that over the next few videos, we're going to be using
-
0:34
some concepts that you haven't fully learned yet but will soon.
-
0:38
So take this as a series of bonus videos.
-
0:41
It's up to you if you want to implement these changes, but
-
0:43
I highly encourage you to just watch along anyway.
-
0:46
Let's review our potential set of problem areas.
-
0:49
The first thing I don't like is the fact that the code that sets up our different
-
0:53
views is all over the place inside the view controller.
-
0:56
And I'm talking about the PageController at the moment.
-
0:59
We've declared the labels and
-
1:00
the buttons, up at the top over here, as stored properties.
-
1:05
Then there's some setup code related to these image views, buttons, labels, and so
-
1:09
on, inside viewDidLoad as you can see here.
-
1:13
And then finally, there's some more in viewWillLayoutSubviews.
-
1:18
In fact, viewDidLoad does a lot of different things and
-
1:21
its responsibilities aren't entirely clear or straightforward.
-
1:26
One of these responsibilities, as you can see here,
-
1:28
is creating an attributed string with a certain set of styles.
-
1:33
This doesn't really need to be in viewDidLoad.
-
1:35
Maybe we can put this elsewhere.
-
1:37
We're also setting up buttons with choices.
-
1:40
Perhaps we can get all of this out of viewDidLoad as well.
-
1:44
So how do we proceed here?
-
1:46
Recently, we learned about lazy stored properties,
-
1:49
which are stored properties that aren't created until the need arises.
-
1:54
There's an interesting thing we can do with lazy stored properties that
-
1:57
can help us clean up our code.
-
1:59
Now you haven't learned about this yet, but we can also create what are called
-
2:03
anonymous functions that are immediately executed.
-
2:06
And we're going to use that, to improve our code, to make a few changes so
-
2:10
that we can either group all of the logic in one place and
-
2:13
get it out of these methods altogether.
-
2:15
So let's look at how we'll use these concepts.
-
2:18
I'm gonna go back up to the top.
-
2:20
Imagine we had a stored property, a variable named a property,
-
2:25
to which we assign the value, 1.
-
2:28
Now instead of assigning this value 1 directly,
-
2:31
I'm going to assign a function to it.
-
2:34
Now what you see here, just an opening and closing set of braces
-
2:38
that has nothing in it, this is an anonymous function or a closure.
-
2:43
And you'll learn more about this pretty soon, but
-
2:45
essentially think of this as a function without a name right now.
-
2:49
So this works exactly like a normal function.
-
2:51
So inside it, I'm going to return the value 1.
-
2:55
All I've done here is define the function.
-
2:57
And if you check the type of a property, it's the function signature.
-
3:01
So it's a function that does not take any values, no arguments, but
-
3:05
returns an integer.
-
3:06
With regular functions,
-
3:08
when we want to call it, we write the name of the function or the method.
-
3:12
And then using a set of parentheses,
-
3:15
we hold the function, passing in any arguments if the function needs it.
-
3:19
With functions that don't take arguments this means putting an empty set of
-
3:22
parentheses right after the function name to call it.
-
3:26
As you can see here in viewDidLoad.
-
3:27
So it's just the function name and a set of empty parentheses.
-
3:31
Since this function, that we just wrote, is not named, to call it we can place
-
3:36
an empty, or a set of empty parentheses, right after it, immediately after it.
-
3:41
In addition, if we annotate the property, so
-
3:44
we'll say aProperty, explicitly we'll set the type to int.
-
3:49
What we have now is essentially the value 1 being assigned to aProperty.
-
3:55
This is a very roundabout way of simply assigning 1 like we did earlier, but
-
4:00
it opens up some interesting possibilities.
-
4:02
So here we have an anonymous function that returns the value 1,
-
4:05
that is immediately called.
-
4:08
So this executes, and we return 1, and we assign 1 to aProperty.
-
4:13
Using these anonymous functions,
-
4:14
we can group together logic related to our elements, all at the point of creation.
-
4:19
So everything related to the label can be put in this one place.
-
4:23
Let's start and we'll try this with the story label.
-
4:27
So rather than assigning an instance of UILabel directly.
-
4:31
First, we're going to get rid of this instance that we're assigning here.
-
4:36
Make some room so that we can see what's going on.
-
4:39
And again, we're going to explicitly specify the type as UILabel.
-
4:44
Now the reason we're doing this, like we did here with Int,
-
4:48
is because we're assigning a function here.
-
4:51
We need to let the compiler know exactly what it is we're
-
4:54
returning from the function, and what the type of this property will be.
-
4:58
So let's get rid of this, we don't need this anymore.
-
5:02
Now to this property, again,
-
5:04
let's assign an anonymous immediately executing function.
-
5:09
So set of braces just like a function body.
-
5:11
And then right after it,
-
5:12
we'll place the set of empty parentheses to call the function.
-
5:16
Now we have an error, and
-
5:17
that's because this function is expected to return a UILabel value, since
-
5:23
that's what we told the compiler will be the final value that comes out of it.
-
5:27
Now, inside the function, we can set up the instance of the label.
-
5:31
So say let label equal, we'll create a new instance of UILabel.
-
5:36
And then we can go ahead and return it.
-
5:38
And now storyLabel is this instance of UILabel,
-
5:42
except that since this is a function, rather than writing a function below and
-
5:46
assigning the value to this property in viewDidLoad,
-
5:50
we're assigning the function and calling it immediately right here.
-
5:53
So whatever is in this function is executed, and
-
5:55
that value is assigned back to storyLabel.
-
5:57
So inside this function, inside this closure, we can also customize the label.
-
6:02
So we can say label.translatesAutoresizingMaskIntoConst-
-
6:06
raints equal false.
-
6:08
And label.numberOfLines equals zero.
-
6:13
So now that we have this code in here,
-
6:14
this is the same customization we're doing inside viewWillLayoutSubviews.
-
6:19
So if you look here, we're first adding the storyLabel as a Subview,
-
6:23
then we set the number of lines to zero and
-
6:24
turn off the AutoresizingMaskIntoConstraints property.
-
6:28
We've already done that, so we can get these lines of code out of here.
-
6:32
Let's do the same thing, the same basic trick.
-
6:35
It's not really a trick but the same basic thing,
-
6:37
for all of the views that we've added to this view controller.
-
6:41
So instead of assigning an instance of UIImageView, we'll set the type to that
-
6:46
and we'll assign a function that we call immediately.
-
6:52
Inside the body of the function, we'll create a new UIImageView, we'll return it.
-
7:01
So that now we have an instance assigned to the property and
-
7:04
then we can customize this.
-
7:05
So we'll say imageView and we'll do the same basic thing,
-
7:08
translatesAutoresizingMaskIntoConstraints false.
-
7:12
Which means now we can go down to viewWillLayoutSubviews.
-
7:19
Down here, we'll remove this property as well, so
-
7:22
we'll clean it up a little bit more.
-
7:24
We'll go back up and we'll do the same thing for the buttons.
-
7:31
So here we want to set the type.
-
7:36
On firstChoiceButton explicitly to UIButton.
-
7:39
Assign a function that we call immediately.
-
7:44
And in here again, we'll repeat the same basic code that we have.
-
7:46
So let button equal UIButton.
-
7:51
Use the type initializer and specify a .system button.
-
7:56
We'll set the button's AutoresizingMask property to false and return it.
-
8:04
Since this is the exact same way, the secondChoiceButton is set up,
-
8:08
we'll grab all of that and assign it right here.
-
8:13
So now we have all this grouped in one area,
-
8:16
we can go down to viewWillLayoutSubviews.
-
8:21
And we'll remove this and this.
-
8:25
Okay, it's somewhat better.
-
8:26
We've removed some set of code from a different method and
-
8:29
put it in the same place that we're creating the view.
-
8:32
But we didn't get rid of a lot of code.
-
8:35
So in the next video, let's focus on slimming down viewDidLoad even more.
You need to sign up for Treehouse in order to download course files.
Sign up