1
00:00:05,810 --> 00:00:11,110
Hey everybody Caleb Stoltze here with slopes dot com and we're going to continue building out our animal

2
00:00:11,110 --> 00:00:16,300
classifier app with the core M-L model that we built ourselves in this video we're going to go ahead

3
00:00:16,330 --> 00:00:23,080
and enable our application to either pull images from our photo library or utilize the camera to take

4
00:00:23,080 --> 00:00:24,520
an image on the fly.

5
00:00:24,760 --> 00:00:29,920
Now before we begin we should go ahead and create some groups to put our view controllers and our custom

6
00:00:29,980 --> 00:00:31,090
subclasses.

7
00:00:31,270 --> 00:00:37,600
So I'm going to right click on my main folder here and create a new group called controller then I'm

8
00:00:37,600 --> 00:00:40,170
going to right click and do one more and call it view.

9
00:00:40,180 --> 00:00:44,110
And this is just a nice way to keep everything neat and tidy.

10
00:00:44,120 --> 00:00:49,120
We're going to drag our visual effect view into the view folder and we don't have any special models

11
00:00:49,180 --> 00:00:53,320
in this project so we don't really need a model folder.

12
00:00:53,470 --> 00:00:55,570
You know if there's no files to go in it.

13
00:00:55,600 --> 00:01:00,700
So what we're going to do is we're going to actually close the assistant editor and go directly into

14
00:01:00,700 --> 00:01:02,760
the classifier View Controller.

15
00:01:02,950 --> 00:01:10,090
And what we need to do is we need to go ahead and set it up so that we can check if a particular device

16
00:01:10,180 --> 00:01:17,170
has a camera and if it doesn't we're going to go ahead and present the photo picker to choose from the

17
00:01:17,170 --> 00:01:17,820
library.

18
00:01:17,980 --> 00:01:24,360
So first of all we're going to check to make sure that the device that we're using actually has a camera

19
00:01:24,370 --> 00:01:25,950
and to do that we're going to use guard.

20
00:01:25,960 --> 00:01:36,480
So we're going to type guard UI image picker controller that is source type available DOT camera.

21
00:01:36,520 --> 00:01:38,750
We're going to check if it is available.

22
00:01:38,860 --> 00:01:43,900
We will move forward however else or if there is no camera.

23
00:01:44,020 --> 00:01:50,800
We're going to need to present the photo picker OK and then return like so.

24
00:01:51,040 --> 00:01:56,890
And that will essentially present the photo picker without throwing an error or causing a crash because

25
00:01:56,890 --> 00:01:58,510
there's no camera on the device.

26
00:01:58,510 --> 00:02:02,300
This would really only be relevant for really old iPod Touches and iPads.

27
00:02:02,300 --> 00:02:07,090
However since we're going to be using it in the simulator which has no camera it's a pretty good option.

28
00:02:07,240 --> 00:02:14,290
So once we have confirmed that there is or is not a photo device we're going to go ahead and pop up

29
00:02:14,290 --> 00:02:20,590
what is called a photo sourced picture and it's just basically going to use a UI alert controller to

30
00:02:20,620 --> 00:02:24,940
present two options either take a photo or choose a photo from your library.

31
00:02:24,970 --> 00:02:33,290
So let's go ahead and create a constant let photo source picker equals UI alert controller.

32
00:02:33,550 --> 00:02:35,730
And we're going to instantiate it like so.

33
00:02:36,070 --> 00:02:41,590
And now we need to create two separate actions one for take photo and one for choose photo from the

34
00:02:41,590 --> 00:02:42,460
photo library.

35
00:02:42,850 --> 00:02:50,930
So let's go ahead and type Let take photo and we're going to take photo action of type.

36
00:02:50,930 --> 00:02:52,290
UI alert action.

37
00:02:52,300 --> 00:02:56,110
And we're going to give it a title a style and a handler.

38
00:02:56,290 --> 00:02:58,860
So we're going to go ahead and use the title here.

39
00:02:58,880 --> 00:03:00,800
Take photo.

40
00:03:01,210 --> 00:03:04,350
And the style is going to just be default nothing.

41
00:03:04,360 --> 00:03:06,290
No need to do anything fancy here.

42
00:03:06,670 --> 00:03:11,890
And what we're going to do here on this closure is push enter and we don't necessarily need a specific

43
00:03:11,890 --> 00:03:16,900
action here so I'm just going to put an underscore and that will allow me to use the closure without

44
00:03:16,900 --> 00:03:19,180
needing to actually pass anything in.

45
00:03:19,180 --> 00:03:27,370
So what we're going to do here this is where we present the photo picker with the camera option that

46
00:03:27,370 --> 00:03:31,790
will basically present the camera view or we can take a photo and then pass that in later.

47
00:03:32,170 --> 00:03:36,680
So now that action is done now we need to create the choose photo action.

48
00:03:36,820 --> 00:03:40,430
So go ahead and type let choose photo action.

49
00:03:40,900 --> 00:03:44,460
And that's also going to be a UI alert action with a title that will be.

50
00:03:44,460 --> 00:03:46,400
Choose photo.

51
00:03:46,420 --> 00:03:52,430
The style just like the other one will be defaults and the handler are going to do the same thing by

52
00:03:52,540 --> 00:03:54,650
getting rid of this parameter here.

53
00:03:54,670 --> 00:03:57,280
Replacing it with an underscore.

54
00:03:57,460 --> 00:04:06,230
And I'm going to copy this for time's sake but this will instead be the photo picker from your camera

55
00:04:06,230 --> 00:04:09,110
roll or another album of your choice.

56
00:04:09,130 --> 00:04:13,750
So now what we need to do is we need to add these actions to our photo source pictures so we'll type

57
00:04:13,750 --> 00:04:20,430
photo source picture dot add action will pass and take photo action then we're going to do that again.

58
00:04:20,440 --> 00:04:25,070
Photo source Pichler dot add action and pass in Choose photo action.

59
00:04:25,100 --> 00:04:25,680
OK.

60
00:04:25,960 --> 00:04:31,600
And if we actually build this you'll see those warnings will go away and we're now at the point where

61
00:04:31,600 --> 00:04:34,870
we need to also add a cancel action.

62
00:04:35,110 --> 00:04:40,420
So to do that we're going to just type photo source picker adcom AB action and we're going to just go

63
00:04:40,420 --> 00:04:47,800
ahead and create an instance of UI alert action here and we'll just pass in cancell here and the style

64
00:04:47,800 --> 00:04:54,250
is going to be cancell which will show red text and it will also indicate that when it is tapped that

65
00:04:54,250 --> 00:04:59,530
it should just dismiss the view and the handler here we don't care about so we'll just make that nil

66
00:04:59,530 --> 00:05:00,590
because it can be.

67
00:05:00,970 --> 00:05:04,190
And we now have a cancel action which is very cool.

68
00:05:04,540 --> 00:05:12,360
So at point once we've done that we can now present the actual Isler controller which is called Photo

69
00:05:12,360 --> 00:05:13,660
source picker.

70
00:05:14,070 --> 00:05:19,740
We want it to be animated so it looks nice and pretty and the completion we don't care about so we'll

71
00:05:19,740 --> 00:05:26,940
just make that nyl And you know what even though we have not set this up we can go ahead and run this

72
00:05:26,940 --> 00:05:27,870
and see what happens.

73
00:05:27,870 --> 00:05:32,820
I don't think anything will happen because there's no camera available so it should just return when

74
00:05:32,820 --> 00:05:34,640
we press the button.

75
00:05:35,620 --> 00:05:35,950
Yeah.

76
00:05:36,120 --> 00:05:41,100
So nothing's going to happen because we haven't yet set up the picker but I don't know about you but

77
00:05:41,190 --> 00:05:47,550
I want to do that so let's go ahead and let's do that now in order to do that basically we're going

78
00:05:47,550 --> 00:05:51,150
to create a function with two different options.

79
00:05:51,240 --> 00:05:51,980
OK.

80
00:05:52,080 --> 00:05:58,740
And it's going to pass in what's called a source type and it's either going to be a camera or a photo

81
00:05:58,740 --> 00:06:01,070
picker or a library rather.

82
00:06:01,290 --> 00:06:04,800
And with that distinction it's going to present the proper view controller.

83
00:06:04,800 --> 00:06:13,710
So let's go ahead and create a function called Present photo picker and we're going to pass in a source

84
00:06:13,710 --> 00:06:18,650
type of UI image picker controller dot source type.

85
00:06:18,840 --> 00:06:19,620
OK.

86
00:06:20,380 --> 00:06:25,890
And inside this function we're going to go ahead and create an instance of UI image picker controller.

87
00:06:26,010 --> 00:06:31,520
So let's type let picker equals a UI image pick a controller give it an instance.

88
00:06:31,830 --> 00:06:37,620
And we need to set the delegate to be this view controller because this controller is handling the transfer

89
00:06:37,680 --> 00:06:39,740
and passing on of data.

90
00:06:39,780 --> 00:06:47,420
So go ahead and type picker dot delegate equals self and we need to then set the source type of this

91
00:06:47,420 --> 00:06:49,980
picker either camera or photo library.

92
00:06:50,220 --> 00:06:52,990
And don't worry we'll deal with that error in just a second.

93
00:06:53,250 --> 00:06:56,590
But go ahead and type picker source type.

94
00:06:56,640 --> 00:06:58,530
And that's going to be equal to the source type.

95
00:06:58,530 --> 00:07:00,740
We pass in when we call this function.

96
00:07:00,810 --> 00:07:01,510
OK.

97
00:07:01,920 --> 00:07:08,190
At this point we can now type present controller and it will be our picker View Controller.

98
00:07:08,190 --> 00:07:13,170
Animated is true and the completion we don't care about so we'll just make it nil.

99
00:07:13,260 --> 00:07:14,410
So that is that.

100
00:07:14,460 --> 00:07:19,980
But now we need to deal with the fact that we don't yet have the ability to set the delegates and in

101
00:07:19,980 --> 00:07:26,610
order to do that we're going to create an extension of UI image picker control or delegate and UI navigation

102
00:07:26,610 --> 00:07:27,420
control or delegate.

103
00:07:27,420 --> 00:07:30,870
Both are required for us to actually do what we need to do.

104
00:07:31,230 --> 00:07:34,860
So go ahead and let's type extension.

105
00:07:35,970 --> 00:07:38,600
And this view controller is called a classifier controller.

106
00:07:38,610 --> 00:07:44,220
So we're going to create an extension of this Visi and that's going to be UI image picker controller

107
00:07:44,250 --> 00:07:46,060
delegate which you can see right here.

108
00:07:46,320 --> 00:07:50,290
And we're also going to use UI navigation control or delegate.

109
00:07:50,550 --> 00:07:51,740
OK.

110
00:07:52,440 --> 00:07:58,620
Now inside this extension we're going to go ahead and call a function that is a part of UI image picker

111
00:07:58,620 --> 00:08:05,430
controller called did finish picking media with info so you can actually just type that did finish picking

112
00:08:05,700 --> 00:08:07,650
media with info.

113
00:08:07,650 --> 00:08:14,100
See there it is very cool so what we actually get is we get an instance of a picture controller and

114
00:08:14,160 --> 00:08:21,480
we get an array of the info and the data from the actual image itself which is really cool.

115
00:08:21,480 --> 00:08:26,640
So in order to actually move forward this is what happens after we have picked an image either from

116
00:08:26,640 --> 00:08:29,310
the camera or from the photo library.

117
00:08:29,310 --> 00:08:34,500
So we're going to go ahead and just say that the picture can be dismissed and we'll make it animated

118
00:08:34,500 --> 00:08:35,790
so it's nice and pretty.

119
00:08:35,790 --> 00:08:37,290
The completion can be nil.

120
00:08:37,650 --> 00:08:45,090
So at this point the image picker has been dismissed but now we have to take the image from the array

121
00:08:45,090 --> 00:08:49,170
of data here and actually set the image view with that image.

122
00:08:49,200 --> 00:08:54,840
But first we need to pull it out and it is optional in the instance maybe that we don't pick an image

123
00:08:54,840 --> 00:09:00,870
or the image picture control it doesn't successfully you know grab an image when it is taken.

124
00:09:01,320 --> 00:09:08,870
We can go ahead and type guard let image and we're actually going to get that from this info dictionary.

125
00:09:08,880 --> 00:09:14,190
So what we're going to do is we are first going to go ahead and type info that's the name of the dictionary

126
00:09:14,730 --> 00:09:24,330
and we're going to pull out the value for the key image picker controller k dot info key and what we

127
00:09:24,330 --> 00:09:29,160
can do is we can pull out what is called original image and as you can see it specifies the original

128
00:09:29,310 --> 00:09:31,860
uncropped image selected by the user.

129
00:09:31,980 --> 00:09:32,620
OK.

130
00:09:32,880 --> 00:09:38,250
Now the reason we're using a guard left here is because we need to cast this as a UI image so we're

131
00:09:38,250 --> 00:09:45,140
going to type as you image and it is optional because there could not be an image there in that instance.

132
00:09:45,180 --> 00:09:48,980
We're going to type else and we're going to use something called Fatal error.

133
00:09:49,110 --> 00:09:49,630
OK.

134
00:09:49,830 --> 00:09:54,660
And fatal error is something that's used in guard lets in the instance that there is an error that would

135
00:09:54,690 --> 00:09:57,620
interrupt the application from continuing to work.

136
00:09:57,660 --> 00:10:05,510
And so in this instance we're going to say no image returned returned and this is going to be good for

137
00:10:05,510 --> 00:10:06,790
is for development.

138
00:10:06,800 --> 00:10:11,120
Fatal error isn't necessarily the best for production because it would cause your app to crash but give

139
00:10:11,120 --> 00:10:15,390
the user no information on why it crashed.

140
00:10:15,410 --> 00:10:19,790
We're going to talk maybe a little bit later about a better way that we can do this and we'll show you

141
00:10:19,790 --> 00:10:20,880
how to do it.

142
00:10:20,900 --> 00:10:28,010
So now that we have our image here set as a UI image we're going to set our image of you remember that

143
00:10:28,880 --> 00:10:33,740
the image view in our storyboard here this one we're going to fill it with an image so we're going to

144
00:10:33,740 --> 00:10:38,980
type image view dot image and we're going to set it to the image very image constant.

145
00:10:38,990 --> 00:10:46,400
We set right here and at this point once we have an image set we would then be able to use that image

146
00:10:47,210 --> 00:10:54,950
use image to make predictions with core animal model and we're going to call a function later to do

147
00:10:54,950 --> 00:10:55,410
that.

148
00:10:55,460 --> 00:11:01,110
But let's go see if it actually works to select an image and then drop it in our image view.

149
00:11:01,380 --> 00:11:05,490
But first we of course need to actually present our image picture.

150
00:11:05,660 --> 00:11:11,560
So go ahead and type present photo picker and the source type here.

151
00:11:11,570 --> 00:11:14,830
Remember this is in the instance that there is not a camera.

152
00:11:14,900 --> 00:11:18,520
So the source type will be photo library here.

153
00:11:18,530 --> 00:11:27,050
It's for the camera so we can to present photo picker source camera and for this one we can type present

154
00:11:27,650 --> 00:11:29,900
photo picker photo library.

155
00:11:30,080 --> 00:11:30,660
OK.

156
00:11:30,950 --> 00:11:32,060
So let's build it.

157
00:11:32,090 --> 00:11:39,380
And if what we did was correct which actually in this instance it's not because we need to make a reference

158
00:11:39,380 --> 00:11:45,170
to self inside of a closure so type self dot right before this and rebuild.

159
00:11:45,170 --> 00:11:46,710
Forgot about that sorry guys.

160
00:11:46,880 --> 00:11:52,870
And now we should be able to tap on our photo button and be able to select an image.

161
00:11:52,880 --> 00:11:54,370
So tap that button right here.

162
00:11:54,380 --> 00:11:55,110
Boom.

163
00:11:55,220 --> 00:11:57,770
And look at that the images pop right up.

164
00:11:57,770 --> 00:11:59,400
Very cool stuff.

165
00:11:59,480 --> 00:12:06,260
And we can select an image if we click on it it fills the UI image view that is so cool.

166
00:12:06,260 --> 00:12:09,440
One thing though guys the image is currently so squashed.

167
00:12:09,440 --> 00:12:16,190
So I'm going to go into our storyboard and update the content view or content mode rather from scale

168
00:12:16,190 --> 00:12:18,450
to fill to Aspect fill.

169
00:12:18,590 --> 00:12:24,140
And if I go ahead and rebuild that will see that when we select an image it'll actually maintain the

170
00:12:24,140 --> 00:12:25,250
same aspect ratio.

171
00:12:25,270 --> 00:12:33,110
But Phil from top to bottom so click on the camera here go ahead and click on camera roll and there

172
00:12:33,110 --> 00:12:33,440
we go.

173
00:12:33,440 --> 00:12:39,620
Now it's no longer squished it looks really nice and the view behind our label still gives like a hint

174
00:12:39,680 --> 00:12:40,810
of the content behind it.

175
00:12:40,820 --> 00:12:42,410
But we can still read the text fully.

176
00:12:42,410 --> 00:12:44,530
Really really cool stuff.

177
00:12:44,540 --> 00:12:50,360
So we're now at a really good place actually to move into dragging in our core a male model and setting

178
00:12:50,360 --> 00:12:53,100
up some of our classification and prediction functions.

179
00:12:53,110 --> 00:12:55,490
So let's head over to next video and let's do that now.
