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.