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.
