0
1
00:00:00,720 --> 00:00:00,990
All right.
1

2
00:00:00,990 --> 00:00:06,990
So first things first, let's create a new Xcode project and we're going to choose Single View app
2

3
00:00:07,110 --> 00:00:09,590
and I'm just going to call it SeaFood.
3

4
00:00:09,630 --> 00:00:13,860
So we're going to leave all of these unchecked as per usual and we're going to hit Next.
4

5
00:00:14,100 --> 00:00:16,140
And I will save it on my desktop.
5

6
00:00:16,140 --> 00:00:18,210
You can save it anywhere you like.
6

7
00:00:18,210 --> 00:00:24,360
So the first thing we need to do is to incorporate the pre-trained image recognition model into our
7

8
00:00:24,360 --> 00:00:26,430
brand-new Xcode project.
8

9
00:00:26,550 --> 00:00:31,020
So to do that, we're going to head over to Chrome and you're going to go to developer.apple.com/
9

10
00:00:31,020 --> 00:00:37,020
machine-dash learning, and that will take you to Apple's new website that tells you a bit more
10

11
00:00:37,020 --> 00:00:43,080
about how you can add machine learning into your iOS projects and a whole bunch of documentation that
11

12
00:00:43,080 --> 00:00:44,310
is really, really useful.
12

13
00:00:44,340 --> 00:00:50,190
I highly recommend you reading through the CoreML and Vision documentations because we will be using
13

14
00:00:50,190 --> 00:00:52,300
them in our app.
14

15
00:00:52,550 --> 00:00:58,610
So if you scroll down, you'll see this part where it says Working with Models. And at present, they've
15

16
00:00:58,610 --> 00:01:05,660
got four ready-to-use models that you can download and start incorporating into your project.
16

17
00:01:05,660 --> 00:01:11,900
So the one that we're going to be using is a Google's Inception v3. From various sources as well as testing
17

18
00:01:11,900 --> 00:01:12,400
myself,
18

19
00:01:12,410 --> 00:01:17,870
I find that this seems to be working best in terms of image recognition compared to the other ones.
19

20
00:01:17,900 --> 00:01:22,130
So if you actually look at all four, they're actually all image recognition models.
20

21
00:01:22,220 --> 00:01:25,300
But from my own experience, I find that this one works the best,
21

22
00:01:25,310 --> 00:01:27,890
so this is the one that we're going to be using in the tutorial.
22

23
00:01:28,160 --> 00:01:35,080
So go ahead and click download CoreML model and you can see it's not actually all that big.
23

24
00:01:35,120 --> 00:01:41,990
It's about the size of a raw image file, so it's 94 megabytes, and shouldn't take that long to download.
24

25
00:01:41,990 --> 00:01:46,270
All right, so once you've got it downloaded, you'll see that the file looks something like this.
25

26
00:01:46,280 --> 00:01:48,480
It's a .mlmodel file.
26

27
00:01:48,500 --> 00:01:52,060
So we're going to be dragging this into our Xcode project.
27

28
00:01:52,100 --> 00:01:58,940
So if you head over to your Xcode project, you're going to drag that Inceptionv3 file into the
28

29
00:01:58,940 --> 00:02:04,220
file structure of your Xcode project. So simply just click and drag and just drop it somewhere inside
29

30
00:02:04,220 --> 00:02:05,720
the SeaFood folder.
30

31
00:02:05,720 --> 00:02:12,140
Make sure that the checkbox "Copy items if needed" is checked, and then go ahead and click Finish.
31

32
00:02:12,380 --> 00:02:14,130
So that's going to take a little while
32

33
00:02:14,180 --> 00:02:20,680
as Xcode incorporates it into your project. But once it's done, you'll see it appear in the file structure.
33

34
00:02:20,750 --> 00:02:27,320
And also if you click on it, you can actually see that Xcode has created a model class for this model
34

35
00:02:27,320 --> 00:02:28,400
that we just dropped in.
35

36
00:02:28,400 --> 00:02:31,040
You can actually see what that wrapper looks like.
36

37
00:02:31,040 --> 00:02:35,280
So here, you can see that this is the variable that we're going to be working with the most.
37

38
00:02:35,300 --> 00:02:41,220
This is the Inceptionv3 model and we're going to be using it to do all of our image recognition tasks.
38

39
00:02:41,240 --> 00:02:41,560
All right.
39

40
00:02:41,570 --> 00:02:45,990
So let's start writing some code and incorporate our model into our ViewController.
40

41
00:02:46,010 --> 00:02:47,840
So first of al,l I'm going to get rid of this
41

42
00:02:47,840 --> 00:02:53,750
didReceiveMemoryWarning and this line of comments just to clean up the ViewController, so you can see
42

43
00:02:53,750 --> 00:02:56,080
more clearly what I'm doing.
43

44
00:02:56,150 --> 00:03:01,110
So the first thing we have to do when we use any sort of framework is, of course, import it, so I'm going to
44

45
00:03:01,160 --> 00:03:03,390
import CoreML,
45

46
00:03:03,710 --> 00:03:08,630
and I'm also going to import another new framework which is called Vision.
46

47
00:03:08,960 --> 00:03:16,280
So Vision is going to help us process images more easily and allow us to use images to work with CoreML
47

48
00:03:16,610 --> 00:03:18,910
without writing a whole lot of code.
48

49
00:03:19,010 --> 00:03:24,110
So once we've imported all the framework that we need, the next thing that we need to do is to set up
49

50
00:03:24,230 --> 00:03:29,960
our UI Image Picker class and this is going to allow us to tap into the camera, as well as choose the
50

51
00:03:29,960 --> 00:03:32,880
image that we're going to use for our image recognition.
51

52
00:03:33,020 --> 00:03:37,650
So it's pretty straightforward and I'll show you that it's actually pretty easy to get set up.
52

53
00:03:37,730 --> 00:03:42,860
So the first step in setting a UI Image Picker class is to declare some delegate protocols.
53

54
00:03:42,950 --> 00:03:48,050
So we're going to write comma, UIImagePickerControllerDelegate.
54

55
00:03:48,080 --> 00:03:51,520
So there's actually quite a few that look all very, very similar.
55

56
00:03:51,590 --> 00:03:58,640
Let's make sure that you pick the right one, not UIPickerControllerDelegate, but UIImagePickerControllerDelegate,
56

57
00:03:58,760 --> 00:04:01,030
and go ahead and hit enter.
57

58
00:04:01,400 --> 00:04:04,140
And for UIImagePickerController to work,
58

59
00:04:04,160 --> 00:04:07,560
it also needs the UINavigationControllerDelegate.
59

60
00:04:07,580 --> 00:04:09,190
So we're going to add that here as well.
60

61
00:04:09,230 --> 00:04:16,040
SoUINavigationControllerDelegate, not UINavigationController, and not any of the other ones.
61

62
00:04:16,070 --> 00:04:20,820
Make sure that it reads exactly the same as I've got here on screen.
62

63
00:04:20,840 --> 00:04:27,120
Now, as I mentioned, the UIPickerViewDelegate relies on a UINavigationControllerDelegate.
63

64
00:04:27,290 --> 00:04:34,770
So let's head over to the Main.Storyboard and embed our empty View Controller inside a Navigation Controller.
64

65
00:04:34,790 --> 00:04:36,550
So do you remember how to do this?
65

66
00:04:36,590 --> 00:04:40,540
If you do, then go ahead and pause the video, and just do it yourself.
66

67
00:04:40,550 --> 00:04:42,740
Otherwise, I'll show you how it's done.
67

68
00:04:42,770 --> 00:04:47,330
So, if you don't remember, all you have to do is click on the View Controller, and make sure that that
68

69
00:04:47,510 --> 00:04:54,740
little yellow spot is selected, and then you go into Editor, and you go into Embed In, and instead of
69

70
00:04:54,870 --> 00:05:02,060
Tab Bar Controller, which is the one with the tabs at the bottom, we're going to pick Navigation Controller.
70

71
00:05:02,120 --> 00:05:09,860
So this gives us a free nav bar, which is that bar at the top, that allows us to navigate between screens very
71

72
00:05:09,860 --> 00:05:11,950
easily going back and forth.
72

73
00:05:11,990 --> 00:05:15,880
Now, in the nav bar, we're going to add a button.
73

74
00:05:16,130 --> 00:05:23,420
So if you go into your object library and search for bar button item bar, button item, then this is the
74

75
00:05:23,420 --> 00:05:24,650
first thing that should show up,
75

76
00:05:24,690 --> 00:05:30,540
and this is a free button that you get to use by incorporating the Navigation Controller.
76

77
00:05:30,830 --> 00:05:36,950
So you can go ahead and click and drag that and we're going to just drop it on the top right-hand corner.
77

78
00:05:36,950 --> 00:05:40,280
So this is the top right of a navigation bar.
78

79
00:05:40,280 --> 00:05:46,160
Now, you can see, by default, it's called Item, but instead, we want to get a free image in here.
79

80
00:05:46,400 --> 00:05:51,630
So if you go ahead into the system item, instead of Custom, we're going to change it
80

81
00:05:52,080 --> 00:05:56,790
to Camera, and you can see, we've got a nice little camera icon now set up.
81

82
00:05:56,880 --> 00:06:02,250
So while we're in the Main.storyboard, let's finish setting up the rest of our interface.
82

83
00:06:02,310 --> 00:06:07,620
So if you go into, again, the object library, and find an image view, this is the image view that we're
83

84
00:06:07,620 --> 00:06:13,290
going to be using to display the image that was taken from the camera or the image that was picked from
84

85
00:06:13,290 --> 00:06:14,640
the photo album.
85

86
00:06:14,640 --> 00:06:21,730
So what I'm going to do is I'm going to place it at the top and drag it to fill the entire 
86

87
00:06:21,730 --> 00:06:22,570
ViewController.
87

88
00:06:22,590 --> 00:06:27,300
Now, I'm going to set some constraints so that it displays nicely on different screen sizes.
88

89
00:06:27,540 --> 00:06:33,540
And I'm going to constrain with zero points to all four sides, and make sure that the constrained margin's
89

90
00:06:33,780 --> 00:06:35,810
checkbox is unchecked.
90

91
00:06:35,850 --> 00:06:38,250
Go ahead and click add for constraints.
91

92
00:06:38,580 --> 00:06:44,780
Now, ever since iOS 11, you'll see that it says that bottom and top layeout guides are deprecated.
92

93
00:06:44,970 --> 00:06:51,900
Now, what this means is that the top part here and the bottom part here is no longer a valid constraint
93

94
00:06:51,900 --> 00:06:53,490
setting.
94

95
00:06:53,490 --> 00:06:59,660
Now, to fix this, all you need to do is to go into the file inspector.
95

96
00:06:59,850 --> 00:07:06,570
If you scroll down, you can see that there is this option where it says, "Use Safe Area Layout Guides," and
96

97
00:07:06,630 --> 00:07:12,420
if you check it, your errors will go away, because it will automatically replace the top and bottom layout
97

98
00:07:12,500 --> 00:07:17,330
guides with safe area layout guides, and you won't have any problems with that anymore.
98

99
00:07:17,520 --> 00:07:19,270
So, now that the design is set up,
99

100
00:07:19,320 --> 00:07:23,620
of course, we need to set up some IBActions and IBOutlets.
100

101
00:07:23,640 --> 00:07:27,320
So the first IBAction I'm going to set up is the one from the camera.
101

102
00:07:27,450 --> 00:07:33,750
So we're just going to control and drag and I'm going to call that cameraTapped.
102

103
00:07:33,990 --> 00:07:36,630
Make sure that you change the Connection to Action
103

104
00:07:36,660 --> 00:07:41,600
and I'm going to change the type to UIBarButtonItem, hit Connect, and that's done.
104

105
00:07:41,850 --> 00:07:48,540
The next thing I want to do is control drag the UIImageView and I'm just going to call this
105

106
00:07:48,550 --> 00:07:48,950
ImageView.
106

107
00:07:49,110 --> 00:07:54,120
You can be more precise if you want, and you probably should be, especially, if your project is going to
107

108
00:07:54,120 --> 00:07:55,120
be a lot bigger.
108

109
00:07:55,290 --> 00:08:00,370
But for demo purposes, I'm going to call it ImageView because that makes the most sense at this stage.
109

110
00:08:00,450 --> 00:08:06,310
So let's go ahead and click Enter or Connect and that will connect up our brand-new ImageView.
110

111
00:08:06,450 --> 00:08:07,260
And there we go.
111

112
00:08:07,320 --> 00:08:09,740
And that's it. We're done with our design.
112

113
00:08:09,750 --> 00:08:17,720
So let's head back into our ViewController and continue and finish setting up our UIPickerViewDelegate.
113

114
00:08:18,140 --> 00:08:24,720
So, so far, all that we've done for the UIPickerViewDelegate. i.e., enabling our app to use the camera and
114

115
00:08:24,780 --> 00:08:29,550
to pick images is adding in these two delegate protocols.
115

116
00:08:29,550 --> 00:08:29,840
All right.
116

117
00:08:29,850 --> 00:08:34,860
So the next thing I'm going to do is I'm going to create a new image picker object.
117

118
00:08:34,890 --> 00:08:44,430
So just below the IBOutlet, I'm going to write let imagePicker = UIImagePickerController, and make
118

119
00:08:44,430 --> 00:08:52,160
sure you add the empty parentheses as we are creating a new object from the class UIImagePickerController.
119

120
00:08:52,500 --> 00:08:58,980
So, now that we've created that imagePicker object, the next thing we need to do is to set its delegate
120

121
00:08:59,220 --> 00:09:00,610
as this current class.
121

122
00:09:00,630 --> 00:09:06,140
So we're going to write imagePicker.delegate = self ,i.e.,
122

123
00:09:06,150 --> 00:09:08,150
this current ViewController.
123

124
00:09:08,160 --> 00:09:14,550
Now, if you get any errors at this stage, just go back and check to make sure that up here you've got
124

125
00:09:14,550 --> 00:09:19,530
UIImagePickerControlDelegate and UINavigationControllerDelegate.
125

126
00:09:19,710 --> 00:09:25,570
And when you've created your imagePicker, it is an object of the class UIImagePickerController.
126

127
00:09:25,800 --> 00:09:30,660
Now, there's many, many variations that look really, really similar to all of these things and it's very
127

128
00:09:30,660 --> 00:09:31,620
easy to trip up,
128

129
00:09:31,620 --> 00:09:34,270
so just double check if you're getting any errors.
129

130
00:09:34,350 --> 00:09:36,870
If you're when you're at this stage.
130

131
00:09:37,290 --> 00:09:42,450
So, now that we've set our imagePicker's delegates, we're also going to set a couple of other properties,
131

132
00:09:42,680 --> 00:09:46,380
and namely, that's the source type and the allows editing.
132

133
00:09:46,380 --> 00:09:53,100
So the first thing we're going to do is set the imagePicker.sourceType property, and as you can see down
133

134
00:09:53,190 --> 00:09:57,440
here is the type of picker interface to be displayed by the controller.
134

135
00:09:57,480 --> 00:10:00,780
So the source type what we want is .camera.
135

136
00:10:00,780 --> 00:10:08,490
So, this brings up a UIImagePicker that contains the camera module, so it allows the user to take an image
136

137
00:10:08,520 --> 00:10:11,000
using the front or the rear cameras,
137

138
00:10:11,040 --> 00:10:16,320
and this is probably the easiest way of implementing the camera functionality in any app.
138

139
00:10:16,320 --> 00:10:20,560
Now, the next thing I want to set is the imagePicker's allowsEditing property,
139

140
00:10:20,820 --> 00:10:22,440
and this is a Boolean value,
140

141
00:10:22,540 --> 00:10:28,380
either true or false, indicating whether the user is allowed to edit a selected image or movie.
141

142
00:10:28,380 --> 00:10:35,100
Now, if you're extending this app, you might want to allow editing because, then, you can let the user crop
142

143
00:10:35,100 --> 00:10:41,910
the image, so that your machine learning model has to work on less area and a more specific area to figure
143

144
00:10:41,910 --> 00:10:43,560
out what that item is.
144

145
00:10:43,620 --> 00:10:48,850
But for now, for ease and simplicity, we're just going to set the allowsEditing to false,
145

146
00:10:48,900 --> 00:10:51,060
so we don't have to trigger that part.
146

147
00:10:51,060 --> 00:10:51,350
All right.
147

148
00:10:51,350 --> 00:10:54,280
So all the setup for imagePicker is done.
148

149
00:10:54,470 --> 00:10:59,310
Now, we have to specify when we want our imagePicker to appear.
149

150
00:10:59,390 --> 00:11:04,380
Now, the most logical point for it to appear is when the camera button is tapped,
150

151
00:11:04,400 --> 00:11:04,880
right?
151

152
00:11:04,970 --> 00:11:11,360
So all we have to do is to go into our IBAction that we created earlier on inside camera tapped and
152

153
00:11:11,360 --> 00:11:18,920
say present, because it's a ViewController, bracket, and we're going to pick this first one where we're
153

154
00:11:18,920 --> 00:11:25,070
presenting a View Controller, and we can specify whether it should be animated presentation or
154

155
00:11:25,070 --> 00:11:30,170
not, and also whether to do something once the presentation is done.
155

156
00:11:30,350 --> 00:11:36,080
So just go ahead and hit enter to insert all of that template code and the ViewController that we want to
156

157
00:11:36,080 --> 00:11:41,480
present is, of course, our imagePicker of the class UIImagePickerController,
157

158
00:11:41,510 --> 00:11:47,820
so I'm just going to write imagePicker, animated, we'll set as true, and completion, we'll set as nil.
158

159
00:11:47,840 --> 00:11:52,190
We don't really want anything to happen after we finish presenting that imagePicker,
159

160
00:11:52,180 --> 00:11:55,420
because we want our user to start taking photos.
160

161
00:11:55,460 --> 00:11:57,700
So let's just quickly recap what we've done.
161

162
00:11:57,800 --> 00:12:03,320
We've set this view controller, this current ViewController as a delegate of the UIImagePickerContnroller,
162

163
00:12:03,320 --> 00:12:07,790
as well as of the UINavigationController.
163

164
00:12:08,050 --> 00:12:15,710
Then we created a new UIImagePickerController object, and we set all of its properties including its
164

165
00:12:15,710 --> 00:12:19,190
delegate, its source type, and whether it allows editing.
165

166
00:12:19,190 --> 00:12:25,670
Finally, when the camera button gets tapped, we're asking the app to present this imagePicker to the user
166

167
00:12:26,030 --> 00:12:30,800
so that they can use the camera or use the photo album to pick an image.
167

168
00:12:30,800 --> 00:12:33,220
So what is the natural next step?
168

169
00:12:33,260 --> 00:12:39,890
Well, what should happen once they've picked that image? We should be sending that image to our machine
169

170
00:12:39,890 --> 00:12:41,130
learning model, right?
170

171
00:12:41,360 --> 00:12:48,590
So in order to address that timepoint, i.e., the time point where the user has picked an image, we need
171

172
00:12:48,590 --> 00:12:54,110
to add in a delegate method, and I'm going to add it just below the viewDidLoad and above the
172

173
00:12:54,110 --> 00:12:55,880
cameraTapped IBAction.
173

174
00:12:55,880 --> 00:13:02,480
Now, the delegate method comes from the UIImagePickerController class and its called 
174

175
00:13:02,480 --> 00:13:06,540
imagePickerController didFinishPickingMediaWithInfo.
175

176
00:13:06,920 --> 00:13:13,550
So I'm just going to start writing the most specific part of it which is didFinishPickingMediawithInfo,
176

177
00:13:13,580 --> 00:13:19,160
and you can see I didn't even need to finish all of that, and Xcode already suggested to me
177

178
00:13:19,190 --> 00:13:20,870
the one that I probably want.
178

179
00:13:20,870 --> 00:13:23,970
So this is the delegate method that tells the delegate,
179

180
00:13:23,990 --> 00:13:28,960
i.e., this ViewController class that the user has picked an image or a movie.
180

181
00:13:28,970 --> 00:13:35,000
So, basically, this is the time point where they've picked an image, the're done, you want to do something
181

182
00:13:35,000 --> 00:13:36,770
with that image that they picked.
182

183
00:13:36,770 --> 00:13:41,510
So go ahead and hit enter and I'm going to talk through some of these parameters.
183

184
00:13:41,870 --> 00:13:47,260
So the picker was the UIImagePickerController that was used to pick the image,
184

185
00:13:47,300 --> 00:13:50,650
and in this case, that would be our imagePicker object here.
185

186
00:13:50,690 --> 00:13:57,920
The next thing is that didFinishPickingMediaWithInfo and the info is in the format of a dictionary.
186

187
00:13:57,920 --> 00:14:06,970
Now, inside the info parameter contains the image that the user picked and we're going to tap into it
187

188
00:14:07,070 --> 00:14:08,810
Inside the delegate method.
188

189
00:14:08,810 --> 00:14:15,290
So go ahead and click on that code placeholder and hit backspace to delete it. And the first thing I'm
189

190
00:14:15,290 --> 00:14:19,190
going to check to make sure that an image was indeed picked,
190

191
00:14:19,310 --> 00:14:21,310
i.e., it wasn't nil.
191

192
00:14:21,470 --> 00:14:27,680
So to do that, I'm going to create a constant called image and it is going to be set to the image that the
192

193
00:14:27,680 --> 00:14:29,540
user picked using the
193

194
00:14:29,540 --> 00:14:32,690
imagePickerController. So to tap into it,
194

195
00:14:32,720 --> 00:14:39,140
I'm going to tap into this info parameter, which as you can see is a dictionary, and I'm going to specify
195

196
00:14:39,170 --> 00:14:46,880
the key that will yield that image that they picked, and the key is called 
196

197
00:14:46,880 --> 00:14:53,700
UIImagePickerControllerOriginalImage. And this is the original unedited image selected by the user.
197

198
00:14:53,730 --> 00:14:58,440
So this will be the image coming out of the camera or the original image that the user selected from
198

199
00:14:58,440 --> 00:14:59,600
the photo album.
199

200
00:14:59,790 --> 00:15:03,680
So go ahead and click enter for it to be automatically written.
200

201
00:15:03,750 --> 00:15:09,270
And now we have a way of accessing the image that the user has picked.
201

202
00:15:09,330 --> 00:15:14,400
So, now that we've gotten hold of the image that the user has selected, the next thing we want to do is
202

203
00:15:14,400 --> 00:15:21,590
we want to set the image view in the background of the app to that image that they've picked.
203

204
00:15:21,600 --> 00:15:25,990
So in order to do that, remember that we had this IBOutlet called imageView.
204

205
00:15:26,040 --> 00:15:27,620
We're going to tap into it,
205

206
00:15:27,720 --> 00:15:31,630
so imageView, and we're going to tap into its image property,
206

207
00:15:31,980 --> 00:15:37,100
so the image that it should be displaying, and we're going to set it to this image that the user picked.
207

208
00:15:37,320 --> 00:15:39,560
Now, you can see here, as I'm typing it,
208

209
00:15:39,690 --> 00:15:45,990
firstly, it looks a little bit confusing because we called it image, we could have been more precise
209

210
00:15:46,440 --> 00:15:50,520
by calling it something like userPickedImage.
210

211
00:15:50,750 --> 00:15:57,960
And that way, when you're writing this line, you can see that this is a lot more explicit than having
211

212
00:15:57,960 --> 00:15:59,910
imageView.image = image,
212

213
00:15:59,970 --> 00:16:00,430
right?
213

214
00:16:00,630 --> 00:16:03,270
So let's change that to that.
214

215
00:16:03,690 --> 00:16:09,300
So in this case, what we're trying to say is that the imageView's image property should be set to the
215

216
00:16:09,300 --> 00:16:13,140
userPickedImage from that imagePickerController.
216

217
00:16:13,170 --> 00:16:19,920
Now, you'll see the Xcode is going to give you an error saying that you can't assign a value of type
217

218
00:16:19,980 --> 00:16:25,680
'Any?' so it's an optional to a type optional 'UIImage?'
218

219
00:16:25,680 --> 00:16:33,120
And the reason why it's saying this is because we're picking out an item from this info dictionary.
219

220
00:16:33,300 --> 00:16:40,200
We're providing a key to that dictionary and we're getting a value out of that dictionary based from that
220

221
00:16:40,200 --> 00:16:48,600
key. But Xcode doesn't know what is the data type of that value because it's not explicit. As you can
221

222
00:16:48,600 --> 00:16:57,780
see here that this info dictionary has a key data type of string, but a value data type of any, i.e., any
222

223
00:16:57,780 --> 00:16:58,690
data type,
223

224
00:16:58,770 --> 00:17:01,130
and that's not very specific.
224

225
00:17:01,140 --> 00:17:06,270
Now, the reason why it's giving you this error is because it doesn't want to try and put some piece of
225

226
00:17:06,270 --> 00:17:13,930
data that is not of UIImageDataType into the imageView because, otherwise, your app would crash,
226

227
00:17:14,070 --> 00:17:16,420
so this is why it's giving you that warning.
227

228
00:17:16,680 --> 00:17:22,270
So let's use optional binding and downcasting to make this more explicit.
228

229
00:17:22,410 --> 00:17:30,720
So I'm going to downcast this data type, which currently has a dataType Any, into a UIImageView.
229

230
00:17:30,720 --> 00:17:31,190
To do that,
230

231
00:17:31,190 --> 00:17:41,660
I'm going to write the "as?" and I'm going to write UIImage. So, now I'm saying that this
231

232
00:17:41,660 --> 00:17:51,140
data should be a UIImageDataType, but I'm going to also add an "if" in front of my "let" to make this
232

233
00:17:51,260 --> 00:17:52,790
an optional bind.
233

234
00:17:52,820 --> 00:18:05,410
So that means that if this piece of data can be downcast into a UIImageDataType, then you should execute
234

235
00:18:05,680 --> 00:18:09,080
this line of code in between these curly braces.
235

236
00:18:09,210 --> 00:18:16,450
And, of course, what we want to happen is setting the imageView's image property to that userPIckedImage
236

237
00:18:16,540 --> 00:18:18,600
that we got out of that.
237

238
00:18:18,970 --> 00:18:22,990
And that makes our code safer more readable and more explicit,
238

239
00:18:22,990 --> 00:18:24,740
and all of our errors disappear.
239

240
00:18:24,970 --> 00:18:32,110
So the final thing that we need to do is we're going to dismiss that imagePicker and go back to our
240

241
00:18:32,110 --> 00:18:33,140
View Controller.
241

242
00:18:33,250 --> 00:18:34,460
So it's very easy.
242

243
00:18:34,480 --> 00:18:44,090
All we have to do is just write imagePicker.dismiss, animated:true, completion:nil.
243

244
00:18:44,100 --> 00:18:54,010
So let's now test out our app and see if it works. And you can see that the app crashes and you see
244

245
00:18:54,040 --> 00:18:56,910
a error log inside your debug console.
245

246
00:18:56,920 --> 00:19:02,380
So if you have a look in here, it says the problem is to do with access.
246

247
00:19:02,500 --> 00:19:09,400
And it says, "This app has crashed because it attempted to access privacy-sensitive data without a usage
247

248
00:19:09,400 --> 00:19:10,450
description.
248

249
00:19:10,450 --> 00:19:12,230
So that's pretty clear cut, right?
249

250
00:19:12,280 --> 00:19:19,240
So all we need to do is to go into the info.plist, which you'll find in here, and we're going to add
250

251
00:19:19,330 --> 00:19:21,610
some property list keys.
251

252
00:19:21,790 --> 00:19:28,540
So go ahead to this line where it says Information Property List, click Add, and if you scroll down, you'll
252

253
00:19:28,540 --> 00:19:28,990
see
253

254
00:19:28,990 --> 00:19:33,820
under Privacy, you've got quite a few different privacy usage descriptions.
254

255
00:19:33,820 --> 00:19:39,790
The one that we want is the Camera Usage Description. And this is basically something where we tell the
255

256
00:19:39,790 --> 00:19:41,650
user why we need that camera
256

257
00:19:41,650 --> 00:19:42,560
exactly.
257

258
00:19:42,580 --> 00:19:44,210
You know we're not spying on you.
258

259
00:19:44,290 --> 00:19:47,340
We just need it in order to make the app work.
259

260
00:19:47,350 --> 00:19:53,100
So I'm just going to write something like "We need your camera yo!"
260

261
00:19:53,800 --> 00:20:01,180
And, remember, if you want to enable the user to pick an item from their photo album., you also need to
261

262
00:20:01,180 --> 00:20:02,690
add that privacy
262

263
00:20:02,710 --> 00:20:09,430
where it says, "Privacy-Photo Library Usage," and you also need to add a description here,
263

264
00:20:09,430 --> 00:20:14,830
so "We need your photos!" There we go.
264

265
00:20:14,870 --> 00:20:15,130
Okay.
265

266
00:20:15,140 --> 00:20:19,040
So, now if I rerun this app, you'll see it working beautifully.
266

267
00:20:19,310 --> 00:20:19,570
All right.
267

268
00:20:19,580 --> 00:20:25,790
So I'm going to tap on the camera button and you'll see that user's description show up, and I'm going
268

269
00:20:25,790 --> 00:20:27,590
to click Okay to allow,
269

270
00:20:27,590 --> 00:20:33,350
and you can see that I've now tapped into the camera, and I can change between the front and the back
270

271
00:20:33,350 --> 00:20:34,120
cameras,
271

272
00:20:34,340 --> 00:20:38,690
and also I can take a photo. Now, once I've taken the photo
272

273
00:20:38,730 --> 00:20:46,460
and If I click use photo, instead of retaking, then it should dismiss that ViewController, and it sets that imageView
273

274
00:20:46,460 --> 00:20:49,330
to the image that I took just now.
274

275
00:20:49,640 --> 00:20:50,410
So brilliant.
275

276
00:20:50,420 --> 00:20:56,630
You've already managed to make the camera functionality work and you've implemented the
276

277
00:20:56,630 --> 00:20:57,760
UIImagePickerController.
277

278
00:20:57,790 --> 00:21:03,500
Now I'm going to show you quickly how you can modify your code, so that the user can use their photo
278

279
00:21:03,500 --> 00:21:06,950
album instead of using the camera.
279

280
00:21:06,980 --> 00:21:12,500
So all you have to do is, where it says here, imagePicker.sourceType, instead of camera, all you have to
280

281
00:21:12,500 --> 00:21:14,840
do is just change it to a photoLibrary.
281

282
00:21:14,840 --> 00:21:19,400
So, now if we rerun the app, if I click on the camera button, you see that
282

283
00:21:19,430 --> 00:21:22,970
now it's asking to access all of my photos.
283

284
00:21:22,970 --> 00:21:23,350
All right.
284

285
00:21:23,360 --> 00:21:28,820
So in this lesson, we've learned to how to implement your imagePickerControllerDelegate.
285

286
00:21:28,820 --> 00:21:35,420
We also learned how to incorporate a cool machine learning model into our project. And you can see that
286

287
00:21:35,420 --> 00:21:38,540
both are pretty pain-free and really, really easy to do.
287

288
00:21:38,810 --> 00:21:40,870
So if you haven't done what I've done,
288

289
00:21:40,880 --> 00:21:44,530
go ahead and just follow along and code up your project
289

290
00:21:44,540 --> 00:21:51,140
up till now. In the next lesson, we're going to be tapping into that model and starting to get interpretations
290

291
00:21:51,410 --> 00:21:53,480
based on the trained model.
291

292
00:21:53,570 --> 00:21:54,440
So I'll see you there.
