0 1 00:00:00,700 --> 00:00:05,680 So in this lesson, all I'm gonna do is just a bit of tidy up around our codebase to make it a little 1 2 00:00:05,680 --> 00:00:09,800 bit shorter, a little bit more succinct, and a little bit easier to read. 2 3 00:00:09,850 --> 00:00:15,160 So the first thing I'm gonna do is I'm gonna get rid of our debug options, so for any app that you're 3 4 00:00:15,160 --> 00:00:21,010 putting on to the App Store, you probably don't want those dots confusing the user. And the next thing 4 5 00:00:21,010 --> 00:00:28,420 is I'm gonna get rid of all these comments and this bit of space. And then inside our touchesBegan where 5 6 00:00:28,420 --> 00:00:30,760 we create a new diceScene, 6 7 00:00:30,880 --> 00:00:33,920 I'm actually going to separate that out into its own function. 7 8 00:00:33,930 --> 00:00:40,000 I'm gonna call it addDice and it's going to take a single parameter which is going to be called 8 9 00:00:40,000 --> 00:00:45,270 atLocation, and this is going to be of the type ARHitTestResults. 9 10 00:00:45,280 --> 00:00:52,990 Now, I'm going to take all of this code and put it into addDice. And then, over here, instead, I'm going 10 11 00:00:52,990 --> 00:01:00,060 to just going to call addDice atLocation which is the location that we got from our hitResult. 11 12 00:01:00,070 --> 00:01:05,460 And this is probably a good point to show you a different way of naming your methods in Swift. 12 13 00:01:05,950 --> 00:01:11,710 So, in Swift, there's something called the external parameter and the internal parameter. So we can say 13 14 00:01:11,830 --> 00:01:16,830 addDice atLocation which seems quite expressive when we call it. 14 15 00:01:17,200 --> 00:01:24,280 But when we want to use it inside our method, I don't really want to say atLocation.worldTransform. 15 16 00:01:24,700 --> 00:01:26,710 Just semantically or in English, 16 17 00:01:26,710 --> 00:01:28,910 that doesn't really sound good to me. 17 18 00:01:28,930 --> 00:01:33,760 So instead, I want to be able to write something like location.worldTransform. 18 19 00:01:33,760 --> 00:01:42,190 So I can keep the external parameter as atLocation, but I can change the internal parameter to simply location. 19 20 00:01:42,190 --> 00:01:50,320 So, now I can use location inside the method and still use atLocation outside the method to indicate 20 21 00:01:50,620 --> 00:01:52,900 what kind of input I'm looking for. 21 22 00:01:52,900 --> 00:01:58,600 And this is just a way of making your code more expressive so that somebody else who has never seen 22 23 00:01:58,600 --> 00:02:03,520 your code can have a look at it and be able to get to grips with it relatively quickly. 23 24 00:02:04,010 --> 00:02:04,240 All right. 24 25 00:02:04,240 --> 00:02:11,350 So we've separated that functionality out and I'm going to put this function above the rollAll. 25 26 00:02:11,440 --> 00:02:13,400 Now, this is really, really up to you, 26 27 00:02:13,420 --> 00:02:18,970 and this is completely personal, I would say. But I think it makes more sense hierarchically. 27 28 00:02:19,240 --> 00:02:23,890 I'm going to keep these three as they are, and then I'm going to move on to refactoring this didAdd 28 29 00:02:23,950 --> 00:02:25,130 delegate method. 29 30 00:02:25,210 --> 00:02:31,840 So one of the first things you can do is you can add a pragma mark to separate it out and we'll call this 30 31 00:02:31,840 --> 00:02:38,230 pragma //MARK: - ARSCNViewDelegateMethods. 31 32 00:02:39,730 --> 00:02:43,950 And now, if you have a look in this dropdown, you can see we've got our categories, 32 33 00:02:44,000 --> 00:02:50,920 ARSCNViewDelegateMethods which has only one at the moment. But as your ARKit app gets more complicated, 33 34 00:02:51,240 --> 00:02:55,570 you're going to be putting more delegate methods in here and it'll be nice to be able to split them 34 35 00:02:55,570 --> 00:03:01,480 up. And equally, you could probably also split up the lifecycle methods up here, 35 36 00:03:01,480 --> 00:03:08,860 viewDidLoad, viewWillAppear, et cetera, and maybe your Dice Rendering Methods. 36 37 00:03:08,980 --> 00:03:13,750 Now, you can split this up however you like, but it's just nice when you can actually browse all your 37 38 00:03:13,750 --> 00:03:17,620 methods and properties and have some sort of structure that divides them up. 38 39 00:03:18,220 --> 00:03:25,240 So if you remember, by having that dash in there, you actually get a little line. If you don't have that 39 40 00:03:25,240 --> 00:03:31,670 dash, you only have this bit of text. And I quite liked that line separation, so I tend to have it in there. 40 41 00:03:31,690 --> 00:03:31,930 All right. 41 42 00:03:31,960 --> 00:03:38,230 So let's look at this renderer didAdd method, and one of the first things that you notice that is 42 43 00:03:38,230 --> 00:03:41,270 pretty long-winded are these lines here. 43 44 00:03:41,500 --> 00:03:48,270 If anchor is of the type ARPlaneAnchor, then let planeAnchor = anchor as! ARPlaneAnchor. 44 45 00:03:48,310 --> 00:03:54,490 So this, obviously, is there because I wanted this code to be as expressive as possible so that even a 45 46 00:03:54,490 --> 00:03:57,800 beginner could actually understand what the hell is going on. 46 47 00:03:58,090 --> 00:04:01,930 But now that we're refactoring, let's make this a little bit simpler. 47 48 00:04:02,440 --> 00:04:08,020 So first thing I'm gonna do is I'm actually going to take out all of that code, put it at the bottom 48 49 00:04:08,410 --> 00:04:09,710 and I'm going to comment it out. 49 50 00:04:09,730 --> 00:04:11,770 So right now we're not concerned with that. 50 51 00:04:11,770 --> 00:04:14,560 We just want to shorten all of this junk here. 51 52 00:04:15,040 --> 00:04:21,490 So instead of checking if anchor is off type ARPaneAnchor, and having an "else" statement that returns, 52 53 00:04:21,490 --> 00:04:28,670 we can actually get rid of all of these lines by simply using a "guard" statement. So I can say guard let 53 54 00:04:29,560 --> 00:04:36,700 planeAnchor = anchor as? ARPlaneAnchor. 54 55 00:04:36,880 --> 00:04:41,440 And if the "guard" statement fails, then I'm simply going to return. 55 56 00:04:41,590 --> 00:04:46,790 So that single line of code has replaced all of this code and we can now get rid of it. 56 57 00:04:46,840 --> 00:04:50,370 But before I do that, I just want to show you how it works. 57 58 00:04:50,380 --> 00:04:52,780 So, firstly, let's look at this part. 58 59 00:04:52,810 --> 00:04:58,000 We're saying, "let," this new constant planeAnchor be set equal to anchor, 59 60 00:04:58,210 --> 00:05:04,990 and we're going to try and downcast it from ARAnchor type to ARPlaneAnchor type. 60 61 00:05:04,990 --> 00:05:12,020 Now, if this is not doable, i.e., the anchor that we actually detected was not of the type ARPlaneAnchor 61 62 00:05:12,040 --> 00:05:18,460 or cannot be converted into the type ARPlaneAnchor, then this planeAnchor is going to be an optional 62 63 00:05:18,460 --> 00:05:20,910 that's going to be equal to nil. 63 64 00:05:20,980 --> 00:05:29,140 And in that case, this fails. And then this guard statement will jump to the "else" portion in which case 64 65 00:05:29,200 --> 00:05:32,140 we return and we escape out of this entire function. 65 66 00:05:32,530 --> 00:05:38,740 So this is kind of like having a moat outside of your castle where you're tripping up all the things, 66 67 00:05:39,370 --> 00:05:46,300 you know, all the--all the cavalry, all the foot soldiers, and you're trying to prevent them from 67 68 00:05:46,360 --> 00:05:53,770 entering your main code, and you're just saying escape if this statement happens to trigger. 68 69 00:05:54,640 --> 00:06:00,670 So, now we can get rid of all of this and we can bring back all of our code down here. 69 70 00:06:00,970 --> 00:06:05,280 So the other thing I want to do is I actually want a separate method to create that plane. 70 71 00:06:05,350 --> 00:06:15,720 So I'm going to create another pragma mark down here and let's call it Plane Render Methods or Plane 71 72 00:06:15,780 --> 00:06:24,350 Rendering, I guess that makes more sense. And then I'm going to take all of this and I'm going to put 72 73 00:06:24,350 --> 00:06:31,400 it into a method here called createPlane with, 73 74 00:06:33,240 --> 00:06:42,170 and it takes a ARPlaneAnchor as a parameter and I'm going to paste it in here. 74 75 00:06:43,460 --> 00:06:52,380 So, again, I want to have with or withPlaneAnchor as the external name for this method. And the internal 75 76 00:06:52,380 --> 00:06:52,760 name, 76 77 00:06:52,770 --> 00:06:59,360 I'll just call it planeAnchor, so that we don't have to update our code too much. 77 78 00:06:59,570 --> 00:07:02,720 Okay. So, now we're going to call that method over here. 78 79 00:07:02,760 --> 00:07:08,640 We're going to say createPlane withPlaneAnchor and the anchor is, of course, this one. 79 80 00:07:08,640 --> 00:07:15,510 So let's pass that in there. And then I'm going to make sure that this method actually returns a 80 81 00:07:15,510 --> 00:07:19,280 SCNNode which is the one that I'm gonna be adding as the childNode. 81 82 00:07:19,380 --> 00:07:23,620 So I'm going to store this inside a constant called a planeNode. 82 83 00:07:23,700 --> 00:07:28,200 So planeNode equals the output of this function 83 84 00:07:28,350 --> 00:07:35,070 and, of course, we need to be able to return planeNode here for that to work. 84 85 00:07:35,070 --> 00:07:41,010 And then, finally, I'm gonna say node.addChildNode, and it's going to be playing node that we got 85 86 00:07:41,010 --> 00:07:48,280 back from that method. And all the errors disappear and all is well in the world. 86 87 00:07:48,340 --> 00:07:51,160 So you can probably even refactor this further. 87 88 00:07:51,160 --> 00:07:55,570 Another suggestion I would make is that this plane can actually be its own object. 88 89 00:07:55,570 --> 00:08:02,380 You can see that we're doing a lot of things on this plane, plane.position, planeNode, plane material, 89 90 00:08:02,590 --> 00:08:03,740 plane geometry. 90 91 00:08:03,820 --> 00:08:09,490 But for now, I'm happy with this. And I hope you enjoyed this bonus refactoring lesson and I like the way 91 92 00:08:09,490 --> 00:08:14,890 that our cleaner code looks. If you have any suggestions on future tutorials that you want us to make, 92 93 00:08:15,250 --> 00:08:21,400 then do go ahead and shoot me a message, and we're going to try and figure out what other things that 93 94 00:08:21,400 --> 00:08:25,970 most people want to learn about, and to use it to guide our future course development. 94 95 00:08:26,410 --> 00:08:32,770 So this is all from Angela at the London App Brewery and I hope you'll look forward to more tutorials that 95 96 00:08:32,770 --> 00:08:36,480 we're going to be adding to this course in the coming weeks and months. 96 97 00:08:36,490 --> 00:08:38,850 So thanks for watching this far, and see you soon.