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.