0
1
00:00:00,390 --> 00:00:05,570
In the last lesson, we learn all about the Model-view-controller design pattern.
1

2
00:00:05,940 --> 00:00:10,770
And in this lesson, we're going to apply the theory that we learned to our Quiz App.
2

3
00:00:11,250 --> 00:00:18,450
First, we're going to separate out the part of our code that deals with the quiz data, namely this quiz
3

4
00:00:18,450 --> 00:00:21,810
array and our Questions struct.
4

5
00:00:21,810 --> 00:00:28,700
Go ahead and right-click on that Question.swift file and select New Group from Selection.
5

6
00:00:28,710 --> 00:00:35,130
This is gonna create a folder that contains that Question.swift file and we're going to rename that
6

7
00:00:35,130 --> 00:00:37,200
folder Model.
7

8
00:00:37,200 --> 00:00:40,910
Next, we're gonna do the same thing for our Main.storyboard.
8

9
00:00:41,190 --> 00:00:46,010
So we're going to create a new group and we're gonna call this one the View.
9

10
00:00:46,350 --> 00:00:53,740
Finally, we're going to right-click on the ViewController.swift and create a new group called Controller.
10

11
00:00:53,850 --> 00:00:59,860
So if your OCD like me, feel free to drag the folder around so that they are in the right order.
11

12
00:01:00,090 --> 00:01:08,460
And now that we've set out our MVC structure, the next step is to actually do the work of converting
12

13
00:01:08,460 --> 00:01:12,820
our code into the MVC design pattern. In order to do that,
13

14
00:01:12,840 --> 00:01:19,170
we need to split up of ViewController.swift. The controller should really only be responsible for
14

15
00:01:19,170 --> 00:01:25,230
telling the other components what to do and respond to changes in other components.
15

16
00:01:25,230 --> 00:01:30,660
This means that the ViewController.swift should handle what to do with the user interaction from the
16

17
00:01:30,660 --> 00:01:33,610
view and tell the view what it should display.
17

18
00:01:33,660 --> 00:01:39,270
It should also fetch the relevant data from the model to send to the screen and tell the model to update
18

19
00:01:39,270 --> 00:01:40,360
itself.
19

20
00:01:40,860 --> 00:01:48,330
But at the moment, our view controller is handling all of the quiz data as well as all of the quiz logic.
20

21
00:01:48,330 --> 00:01:51,180
So we first have to separate this part out.
21

22
00:01:51,300 --> 00:01:58,260
Go ahead and right-click on the Model folder, create a new Swift file in there that we'll call the
22

23
00:01:58,320 --> 00:01:59,640
QuizBrain.
23

24
00:01:59,640 --> 00:02:06,300
This is going to be the brain of our quiz and it's going to handle all of the logic. In here, we're going
24

25
00:02:06,300 --> 00:02:13,650
to create a new structure called QuizBrain. And the first thing that I'm going to add to this QuizBrain
25

26
00:02:14,130 --> 00:02:15,680
is my quiz array here
26

27
00:02:15,690 --> 00:02:18,810
that's currently living inside ViewController.swift.
27

28
00:02:19,020 --> 00:02:25,800
So I'm going to cut it out and put it into my QuizBrain. And with a little bit of reformatting,
28

29
00:02:26,010 --> 00:02:30,720
we should now have our quiz as a property of our QuizBrain.
29

30
00:02:30,720 --> 00:02:36,210
Now, we don't need to initialize this quiz property because we've already given it the value that it
30

31
00:02:36,210 --> 00:02:39,940
needs and it's never going to change because it's a constant.
31

32
00:02:40,050 --> 00:02:46,170
And we're also not gonna be adding questions or removing questions in the middle of running our app.
32

33
00:02:46,230 --> 00:02:53,970
Next, we're going to move the questionNumber variable over to the quiz brain as well because the QuizBrain
33

34
00:02:54,000 --> 00:02:59,880
is now going to be the one that's tracking these sort of things to do with the quiz.
34

35
00:02:59,900 --> 00:03:05,360
Now, at this point, if you take a look inside your ViewController, you'll notice that pretty much all hell
35

36
00:03:05,360 --> 00:03:11,270
has broken loose out here, and there will be errors left, right, and center.
36

37
00:03:11,390 --> 00:03:16,860
You might have doubts about whether if you should have started this endeavor at all. But fear not,
37

38
00:03:16,970 --> 00:03:25,850
I'm here, and the result will be worth it, I promise. If we examine our answerPressed function, you can
38

39
00:03:25,850 --> 00:03:29,810
see that it's actually currently fulfilling two roles.
39

40
00:03:29,810 --> 00:03:35,820
One is the answer checking part and two is the quiz progression.
40

41
00:03:35,840 --> 00:03:38,910
So going to the next question.
41

42
00:03:39,050 --> 00:03:46,480
Now, let's create a new instance or new copy of our quizBrain at the top of our view controller.
42

43
00:03:46,910 --> 00:03:53,580
So just below our IBOutlets, we're going to create a new variable called quizBrain.
43

44
00:03:53,810 --> 00:04:01,130
And, of course, the copies of our struct need to be lowercase to begin with, and we're going to create that
44

45
00:04:01,190 --> 00:04:03,800
from our quizBrain structure.
45

46
00:04:04,460 --> 00:04:12,840
So QuizBrain in capitals and then a set of parentheses at the end. And you might need to just hit command
46

47
00:04:12,840 --> 00:04:17,440
B every so often for it to recognize what you're talking about.
47

48
00:04:17,490 --> 00:04:22,850
Now, we can use our QuizBrain inside our ViewController.swift.
48

49
00:04:23,010 --> 00:04:30,600
So next, we're going to move our answer checking logic out of our ViewController.swift and make all
49

50
00:04:30,600 --> 00:04:33,990
QuizBrain handle it instead. To do that,
50

51
00:04:33,990 --> 00:04:37,780
we'll need a function inside our QuizBrain.
51

52
00:04:38,490 --> 00:04:47,100
Now, whenever a function is associated with a structure or a class, basically, some sort of custom type
52

53
00:04:47,640 --> 00:04:51,060
will then, usually, we call it a method.
53

54
00:04:51,060 --> 00:04:53,520
But this is just something that's quite pedantic.
54

55
00:04:53,520 --> 00:04:59,940
In reality, if you hear a functional method, they essentially refer to the same thing a package of instructions
55

56
00:05:00,210 --> 00:05:10,290
wrapped inside a name. So inside the curly braces of my structure QuizBrain, I'm going to create my method
56

57
00:05:10,740 --> 00:05:18,390
which is going to be called checkAnswer. And this method is gonna need an input in order to work.
57

58
00:05:19,020 --> 00:05:22,680
So the input is gonna be the answer that the user chose
58

59
00:05:22,680 --> 00:05:30,790
and this is gonna be a string. Next, we can go into our ViewController and delete this line of code.
59

60
00:05:30,900 --> 00:05:35,550
Instead, we're going to move that functionality to our QuizBrain.
60

61
00:05:35,550 --> 00:05:39,910
We're going to call quizBrain.checkAnswer.
61

62
00:05:40,140 --> 00:05:48,110
And then, we should be able to add the parameter which is userAnswer.
62

63
00:05:48,120 --> 00:05:52,930
And the argument that we're gonna pass in or the value is, of course, going to be this one.
63

64
00:05:53,090 --> 00:05:55,480
It's gonna be userAnswer.
64

65
00:05:55,480 --> 00:06:02,350
Now, if you think this is a little bit excessive in terms of the naming of our method, checkAnswer, userAnswer,
65

66
00:06:02,350 --> 00:06:10,630
userAnswer, then one way of making this a little bit shorter is actually to add an external parameter
66

67
00:06:10,630 --> 00:06:18,160
name. So remember that the parameter name refers to the name of the input that comes into the function.
67

68
00:06:18,160 --> 00:06:27,530
So we can have an internal and an external parameter name in Swift. So for example, if I decided to call
68

69
00:06:27,590 --> 00:06:37,490
the external parameter name answer, then I would be able to use answer here as the external parameter
69

70
00:06:37,490 --> 00:06:38,440
name.
70

71
00:06:38,450 --> 00:06:47,330
Meanwhile, inside the function, I can use the internal parameter name which is that userAnswer right
71

72
00:06:47,330 --> 00:06:48,390
here.
72

73
00:06:48,410 --> 00:06:54,650
Now, what we can also do is we could also simply say that there shouldn't be an external parameter name.
73

74
00:06:55,280 --> 00:07:02,810
And to do that, we simply replace the excel parameter name, so the first part with an underscore. And now
74

75
00:07:02,810 --> 00:07:10,610
inside our ViewController, we can simply write checkAnswer and pass in this as the argument. To remember,
75

76
00:07:10,610 --> 00:07:18,720
the argument is the value that gets passed in as the input. The parameter is the name of the input
76

77
00:07:19,100 --> 00:07:25,940
and we now have an external and an internal parameter name. We use the internal parameter name inside
77

78
00:07:25,940 --> 00:07:31,200
the function. The external parameter name is used when we call the function.
78

79
00:07:31,400 --> 00:07:36,590
And in this case, because we turned it into an underscore, it no longer needs an external parameter name.
79

80
00:07:37,550 --> 00:07:41,480
And method now reads a lot better in English,
80

81
00:07:41,480 --> 00:07:46,610
checkAnswer which answers the check, well, the user's answer, of course, which comes from here.
81

82
00:07:48,540 --> 00:07:55,350
Now, at this point, we get an error that tells us that this userAnswer is actually an optional string.
82

83
00:07:56,010 --> 00:08:00,540
But checkAnswer is, of course, expecting an actual string.
83

84
00:08:01,200 --> 00:08:08,250
So in our case, because we only have two buttons that are linked to this IBAction and they both definitely
84

85
00:08:08,250 --> 00:08:16,440
have a title, we can be fairly confident in force unwrapping this currentTitle. And that turns our
85

86
00:08:16,440 --> 00:08:20,310
userAnswer into a actual string data type.
86

87
00:08:21,480 --> 00:08:29,340
So now let's go back to our QuizBrain and check the userAnswer that was passed in against the actual
87

88
00:08:29,370 --> 00:08:29,900
answer.
88

89
00:08:30,480 --> 00:08:32,600
So let's add our "if" statement here,
89

90
00:08:32,610 --> 00:08:40,530
check to see if the userAnswer is equal to the quiz at the current questionNumber.answer.
90

91
00:08:40,920 --> 00:08:45,560
Well, then in that case, they got it right.
91

92
00:08:45,630 --> 00:08:47,280
So user got it right.
92

93
00:08:48,630 --> 00:08:54,050
But otherwise, then the user probably got it wrong.
93

94
00:08:54,210 --> 00:09:02,340
So now, while we're in the process of implementing the MVC design pattern, we're coming up against a roadblock.
94

95
00:09:02,400 --> 00:09:10,770
Our problem is that the answer checking happens in our quiz brain, but it's our vVewController that's
95

96
00:09:10,770 --> 00:09:17,810
responsible for updating the UI, changing the sender's background color to green or to red.
96

97
00:09:17,850 --> 00:09:26,070
How can we get the result of this check and some method out from the quizBrain and send it over here
97

98
00:09:26,100 --> 00:09:33,710
into the ViewControlle? Well, if you can solve this problem, you might already know how to use Swift
98

99
00:09:33,710 --> 00:09:36,260
functions that have outputs.
99

100
00:09:36,290 --> 00:09:41,870
But if you don't know how to solve this, then head over to the next Swift Deep Dive where we talk about
100

101
00:09:41,870 --> 00:09:45,890
the third type of functions, functions that can have outputs.
