1
00:00:07,140 --> 00:00:10,170
Everybody what's going on this is Caleb with Dev slopes dot com.

2
00:00:10,180 --> 00:00:16,240
And in this video get excited we're going to start using Touch I.D. and face I.D. So pull open your

3
00:00:16,240 --> 00:00:21,670
project and we're going to write a function called authenticate biometrics and that's basically going

4
00:00:21,670 --> 00:00:29,860
to allow us to present our Touch ID pop up and authenticate with our thumb then based on either success

5
00:00:29,890 --> 00:00:30,930
or failure.

6
00:00:31,060 --> 00:00:36,140
We're going to be able to do something and unlock our notes it's very very cool.

7
00:00:36,160 --> 00:00:41,940
So let's go ahead and let's first import a framework called local authentication.

8
00:00:42,130 --> 00:00:48,640
So go ahead and type import local authentication like so and now we have access to all the cool Touch

9
00:00:48,640 --> 00:00:49,810
ID stuff.

10
00:00:49,810 --> 00:00:59,280
So go ahead and write a function down here called phunk authenticates bio metrics.

11
00:00:59,280 --> 00:01:00,320
All right.

12
00:01:00,430 --> 00:01:04,690
And what we're actually going to do is we're going to use a completion handler to determine when we're

13
00:01:04,690 --> 00:01:05,220
done.

14
00:01:05,260 --> 00:01:11,680
So go ahead and type completion and make sure that it's escaping.

15
00:01:11,980 --> 00:01:16,900
And what we're going to do is we're going to pass it a function and we're going to return void which

16
00:01:16,900 --> 00:01:21,700
is like an empty function where we're not returning anything but what we can do is we can actually pass

17
00:01:21,700 --> 00:01:24,130
in a boolean to this function.

18
00:01:24,400 --> 00:01:29,560
Whenever we are finished ok and that we can use that to determine whether we authenticated successfully

19
00:01:29,620 --> 00:01:30,400
or not.

20
00:01:30,400 --> 00:01:36,700
So now we need to do so we need to set up an instance of what's called an L a context and that stands

21
00:01:36,700 --> 00:01:39,170
for local authentication context.

22
00:01:39,220 --> 00:01:46,870
So create that like so let my context equals a context and instantiate it.

23
00:01:46,930 --> 00:01:51,930
Now in L.A. context basically handles all of the local authentication stuff.

24
00:01:51,940 --> 00:01:57,100
It tells us hey what device we using Does it have a touch I.D. sensor or does it have a face I.D. sensor

25
00:01:57,100 --> 00:01:58,250
et cetera et cetera.

26
00:01:58,660 --> 00:02:07,720
And what we can also do here is we can also set up the localized reason string we can type let my localized

27
00:02:08,650 --> 00:02:10,410
reason string.

28
00:02:10,900 --> 00:02:11,290
OK.

29
00:02:11,290 --> 00:02:16,810
And this is what's going to pop up when you want to present face I.D. so we can just say our app uses

30
00:02:18,670 --> 00:02:26,980
Touch ID slash face I.D. to secure your notes just give a reason for why your app needs to use those

31
00:02:26,980 --> 00:02:28,120
services.

32
00:02:28,150 --> 00:02:33,760
And we're also going to create a variable that can be used to hold whatever errors we might receive.

33
00:02:33,760 --> 00:02:41,890
So go ahead and call var off air and to set it to be of type and as air can go ahead and put a question

34
00:02:41,890 --> 00:02:43,340
mark at the end because it is optional.

35
00:02:43,390 --> 00:02:44,710
We might not get in there.

36
00:02:44,860 --> 00:02:49,690
And the reason they're using an s ere is because it has a property called code and we can pull out the

37
00:02:49,690 --> 00:02:51,710
air for a particular error code.

38
00:02:51,720 --> 00:02:58,900
So now what we're going to do is we're going to use a property as part of a context called can evaluate

39
00:02:58,900 --> 00:03:02,010
policy and what that means is we're checking to see.

40
00:03:02,080 --> 00:03:06,160
Can our device actually evaluate Touch ID.

41
00:03:06,160 --> 00:03:11,920
Does it have a sensor because maybe you're building this app on an iPhone 5 without a touch I.D. sensor.

42
00:03:12,160 --> 00:03:14,270
And in that case we're going to present an error.

43
00:03:14,320 --> 00:03:19,930
So go ahead and say if my context DOT can evaluate policy.

44
00:03:20,200 --> 00:03:25,810
Now what is our policy that's already built into local authentication so go ahead and put a dot and

45
00:03:25,810 --> 00:03:28,090
we're going to say L.A. policy.

46
00:03:28,260 --> 00:03:32,460
Well the name is device owner authentication with biometrics.

47
00:03:32,470 --> 00:03:33,070
OK.

48
00:03:33,430 --> 00:03:34,720
So that's what we're going to say.

49
00:03:34,900 --> 00:03:42,400
If we can evaluate a policy with biometrics or with a touch I.D. sensor that is good to go.

50
00:03:42,400 --> 00:03:49,430
Now for the error what we're going to do is we're going to go ahead and pass in off air just like that.

51
00:03:49,840 --> 00:03:50,980
OK.

52
00:03:50,980 --> 00:03:56,070
Now we can do is we can go ahead and pass in some curly brackets if it returns True.

53
00:03:56,200 --> 00:03:56,590
OK.

54
00:03:56,590 --> 00:04:02,500
Because that's what this function returns we're going to go ahead and call my contex dot evaluate policy

55
00:04:03,280 --> 00:04:08,860
and what this is going to do is it's going to actually evaluate our device owner authentication with

56
00:04:08,860 --> 00:04:11,290
biometrics so if we can.

57
00:04:11,290 --> 00:04:16,410
Meaning if we have the sensor then we want to evaluate the device with biometrics.

58
00:04:16,510 --> 00:04:20,730
Now the localized reason we already created my localized reason string.

59
00:04:20,980 --> 00:04:24,730
That's what's going to pop up saying hey why are you why are you using touch ID.

60
00:04:25,000 --> 00:04:30,210
And the reply is going to either have a Boolean for success or failure and an error.

61
00:04:30,340 --> 00:04:36,480
So go ahead and press enter on the completion handler there and just call this success for the error.

62
00:04:36,550 --> 00:04:37,170
I'm going to name it.

63
00:04:37,170 --> 00:04:41,610
Evaluate error because that's what it is it's an error with evaluation.

64
00:04:41,620 --> 00:04:43,160
Maybe we missed our thumb.

65
00:04:43,300 --> 00:04:43,980
OK.

66
00:04:43,990 --> 00:04:45,640
That's going to present an error.

67
00:04:45,640 --> 00:04:52,000
So if successful meaning if success because that's the name of our property if success we're going to

68
00:04:52,000 --> 00:04:58,420
call completion OK from our completion handler and we're going to pass in true because we are done we

69
00:04:58,510 --> 00:05:00,170
successfully authenticate it.

70
00:05:00,520 --> 00:05:05,100
But if there was an error meaning else now what we're going to do is we're going to take our evaluate

71
00:05:05,310 --> 00:05:06,080
in error.

72
00:05:06,250 --> 00:05:11,940
We're going to go ahead and use guard left to pull out the localized description because it is optional.

73
00:05:12,100 --> 00:05:14,320
And then we should present this alert on the screen.

74
00:05:14,320 --> 00:05:29,270
So go ahead and type guard let maybe evaluate evaluate error string equals evaluate air dot localized

75
00:05:29,290 --> 00:05:31,790
description and as you can see that is optional.

76
00:05:31,960 --> 00:05:32,800
We're going to go ahead and call.

77
00:05:32,800 --> 00:05:36,090
Else return meaning if there is no error just return.

78
00:05:36,290 --> 00:05:39,910
But if we're not successful then we definitely have an error.

79
00:05:39,910 --> 00:05:45,020
So we now have an evaluate error string and this is where we want to present an alert.

80
00:05:45,100 --> 00:05:50,320
So let's create the function to present an alert now below authenticate biometrics.

81
00:05:50,320 --> 00:05:55,010
Go ahead and call or or type phunk show alert.

82
00:05:55,300 --> 00:06:01,110
And we want to pass in a message so show alert with message.

83
00:06:01,240 --> 00:06:01,530
OK.

84
00:06:01,600 --> 00:06:05,530
And use an internal parameter of message because that just makes more sense.

85
00:06:05,560 --> 00:06:12,600
That's of course going to be of type string now what we need to do is we need to create a UI alert controller

86
00:06:12,630 --> 00:06:16,920
and a UI alert action and pass in the proper data.

87
00:06:16,920 --> 00:06:19,590
So go ahead and call that alert.

88
00:06:19,900 --> 00:06:24,380
DC equals UI alert controller.

89
00:06:24,780 --> 00:06:28,830
And if we pass in one with a title message and style we're good to go.

90
00:06:28,830 --> 00:06:34,290
Now the title we're just going to say error the message is going to be the message and the preferred

91
00:06:34,290 --> 00:06:36,450
style is going to be alert.

92
00:06:36,470 --> 00:06:38,390
OK like a pop up alert on our screen.

93
00:06:38,910 --> 00:06:43,140
Now we need to go ahead and set an action so that we can just tap OK and dismiss it.

94
00:06:43,350 --> 00:06:51,570
So go ahead and type let action equals UI alert action and go ahead and give it a title style and handler.

95
00:06:51,570 --> 00:06:53,700
Now the title is going to just say ok.

96
00:06:53,740 --> 00:06:54,250
Whoops.

97
00:06:54,270 --> 00:06:55,400
As a string.

98
00:06:55,410 --> 00:06:56,010
OK.

99
00:06:56,430 --> 00:06:58,590
And that's what the button will display.

100
00:06:58,590 --> 00:07:02,260
Now go ahead and for the style it's just going to be default.

101
00:07:02,700 --> 00:07:07,590
And for the handler This is where we're going to go ahead and just pass in nil because we don't care

102
00:07:07,590 --> 00:07:08,610
what happens when we're done.

103
00:07:08,610 --> 00:07:10,070
We just want to dismiss it.

104
00:07:10,230 --> 00:07:14,550
So go ahead and call alert Visi and add action.

105
00:07:14,700 --> 00:07:20,460
OK we're going to pass in that action like so and then we're going to go ahead and present alert VC

106
00:07:20,960 --> 00:07:27,560
like so we want it to be animated and pretty and nice and to completion we want to be nil.

107
00:07:27,570 --> 00:07:27,930
All right.

108
00:07:27,930 --> 00:07:28,910
Very cool.

109
00:07:29,190 --> 00:07:36,820
So now what we can do is we can call show alert with message and we can pass in our evaluate error string.

110
00:07:37,230 --> 00:07:41,400
Now of course if we were not successful we should say completion is false right.

111
00:07:41,400 --> 00:07:46,830
So let's do that because we did not successfully complete our authentication.

112
00:07:47,070 --> 00:07:48,300
So that's great.

113
00:07:48,300 --> 00:07:53,040
That means we're successful we complete otherwise we're not successful.

114
00:07:53,040 --> 00:07:54,480
We don't complete.

115
00:07:54,480 --> 00:08:00,320
But what if for some reason we can't actually use touch ID.

116
00:08:00,330 --> 00:08:00,560
Right.

117
00:08:00,570 --> 00:08:01,280
That's an error.

118
00:08:01,290 --> 00:08:09,420
So we should say else like so and now we need to do an authentication error like if we can't even authenticate

119
00:08:09,660 --> 00:08:11,550
that's where our off air is going to come from.

120
00:08:11,550 --> 00:08:16,820
So go ahead and call guard left and we'll say authentic.

121
00:08:16,860 --> 00:08:23,380
Well it's just too Auth. error string that's going to be equal to off air.

122
00:08:23,760 --> 00:08:25,230
Localized description.

123
00:08:25,470 --> 00:08:28,660
Else we're just going to return.

124
00:08:28,680 --> 00:08:29,500
All righty.

125
00:08:29,670 --> 00:08:33,720
So we've got an airstrip now for authentication like if we can't even authenticate.

126
00:08:33,720 --> 00:08:35,010
We need to do something about that.

127
00:08:35,010 --> 00:08:39,990
So go ahead and call show alert and we're going to pass in the on air string.

128
00:08:40,080 --> 00:08:40,790
OK.

129
00:08:40,800 --> 00:08:44,400
That will present an alert and show what the issue is.

130
00:08:44,400 --> 00:08:47,070
Now you know what I am noticing we are in a closure here.

131
00:08:47,070 --> 00:08:52,890
Evaluate policy so we're going to need to call self show alert and self-doubt show alert here as well

132
00:08:53,150 --> 00:08:55,850
because if I build it it would yell at us for that.

133
00:08:55,860 --> 00:09:01,650
But it's going to give us another problem here cannot convert value of type and as error to expected

134
00:09:01,680 --> 00:09:03,880
argument type and error pointer.

135
00:09:04,170 --> 00:09:04,670
Oh you know what.

136
00:09:04,680 --> 00:09:04,880
OK.

137
00:09:04,890 --> 00:09:07,500
That's because we're passing in an optional value here.

138
00:09:07,530 --> 00:09:11,950
We need to use an ampersand right before that and that makes this an out.

139
00:09:12,000 --> 00:09:16,840
This gives it in our capabilities meaning if there's an error it's going to just be returned to this

140
00:09:17,240 --> 00:09:17,960
is variable.

141
00:09:17,970 --> 00:09:19,320
For us to use.

142
00:09:19,320 --> 00:09:24,870
So go ahead and put an and sign there at the beginning and then that air can be passed back to the variable

143
00:09:24,870 --> 00:09:26,790
off error from the function.

144
00:09:26,790 --> 00:09:27,630
Pretty cool.

145
00:09:27,960 --> 00:09:33,230
So then of course if there's an error we present the alert and we're going to say completion is false

146
00:09:33,240 --> 00:09:35,750
meaning we did not successfully authenticate.

147
00:09:35,760 --> 00:09:36,710
All right.

148
00:09:36,720 --> 00:09:39,140
Now of course this is great.

149
00:09:39,180 --> 00:09:48,570
But what if we're on maybe a version of IOS that is not going to allow us to use touch ID.

150
00:09:48,570 --> 00:09:51,960
IOS 8 is where Touch I.D. became possible.

151
00:09:51,960 --> 00:09:55,840
What if our app is run on iOS 7 that's going to create problems for us.

152
00:09:55,860 --> 00:09:59,310
So let's go ahead and let's make sure that that iOS version is available.

153
00:09:59,430 --> 00:10:04,850
And to do that we can just say if pound sign available wups.

154
00:10:05,160 --> 00:10:07,300
And as you can see you can pass in a platform here.

155
00:10:07,320 --> 00:10:10,510
I'm going to say I Os eight point zero.

156
00:10:10,860 --> 00:10:11,930
OK.

157
00:10:11,940 --> 00:10:12,650
And you know what.

158
00:10:12,750 --> 00:10:18,900
Mac OS also can use Touch ID so if this app were to be a multi-platform app you could also do Mac OS

159
00:10:19,320 --> 00:10:21,580
ten point twelve point one.

160
00:10:21,600 --> 00:10:25,980
That's the first version that was accessible with Touch ID and then at the end you're going to put a

161
00:10:25,980 --> 00:10:31,560
little pound sign and that's going to say anything else that does not except Touch ID.

162
00:10:31,590 --> 00:10:37,390
OK so if we even have it available we're going to go ahead and do all of this authentication.

163
00:10:37,700 --> 00:10:39,840
OK so go ahead and cut and paste it in.

164
00:10:40,110 --> 00:10:45,630
But if we don't have Touch ID available we should also be saying that completion was false because we

165
00:10:45,630 --> 00:10:48,060
couldn't authenticate if we don't have Touch ID.

166
00:10:48,210 --> 00:10:51,110
Now go ahead and say completion false.

167
00:10:51,120 --> 00:10:56,160
So now what we're doing is we're authenticating with biometrics we're using our L.A. context to check

168
00:10:56,190 --> 00:10:57,810
do we have a touch I.D. sensor.

169
00:10:57,930 --> 00:11:04,440
If yes we evaluate if we're successful we pass completion is true if we're not successful we show an

170
00:11:04,440 --> 00:11:07,140
alert and we say completion is false.

171
00:11:07,140 --> 00:11:12,250
If we can't even value it the policy will show an authentication error message and present it then return

172
00:11:12,250 --> 00:11:13,560
the completion as false.

173
00:11:13,750 --> 00:11:18,250
If we don't even have access to any of this we're going to go ahead and complete false.

174
00:11:18,280 --> 00:11:19,210
Pretty cool.

175
00:11:19,540 --> 00:11:24,940
So now we need to think what are we going to do here to actually present what we need what we're going

176
00:11:24,940 --> 00:11:29,260
to do actually is we're going to go ahead and not just simply push the note but we're only going to

177
00:11:29,260 --> 00:11:32,710
push the note if we are successful otherwise we'll present an error.

178
00:11:32,710 --> 00:11:38,870
So let's go ahead and let's make sure that our note that we select is is locked.

179
00:11:38,980 --> 00:11:44,620
And to do that what we're going to do is we're going to say if Note Saray and we're going to pull out

180
00:11:44,680 --> 00:11:52,250
the item at the index path Roe that we selected lock status is equal to locked.

181
00:11:52,270 --> 00:11:57,760
That means we need to authenticate with biometrics so if the status is locked go ahead and call authenticate

182
00:11:57,760 --> 00:12:07,360
biometrics push enter on the completion handler and say Ophth and hated authenticated and if properly

183
00:12:07,570 --> 00:12:15,490
authenticated what we're going to do is we're going to go ahead and say notes array and we're going

184
00:12:15,490 --> 00:12:20,840
to access that same note what's an index path dot row.

185
00:12:21,130 --> 00:12:26,950
And we're going to go ahead and change its lock status to now be unlocked so we can use lock status

186
00:12:26,950 --> 00:12:30,140
flipper and we can pass in the same thing.

187
00:12:30,200 --> 00:12:30,450
OK.

188
00:12:30,470 --> 00:12:33,460
Notes array index path that row lock status.

189
00:12:33,460 --> 00:12:37,330
And you know what to make this a little more pretty.

190
00:12:37,360 --> 00:12:46,100
I'm going to go ahead and just go ahead and say let lock status and just set that to be equal to this

191
00:12:46,170 --> 00:12:51,690
so that I can just pass in that as a constant here so I don't have to duplicate my code twice.

192
00:12:51,690 --> 00:12:55,440
So I have now set the lock status with our lock status flipper.

193
00:12:55,470 --> 00:12:56,850
It's now unlocked.

194
00:12:57,090 --> 00:13:02,760
And what I can do is now I can push the note onto the view controller.

195
00:13:02,760 --> 00:13:05,770
So what I can do is I can say self.

196
00:13:05,880 --> 00:13:09,660
Push note for index path and I can pass in the index path.

197
00:13:09,660 --> 00:13:10,550
Pretty cool stuff.

198
00:13:10,560 --> 00:13:20,580
But the problem is that when you actually push a controller onto a UI navigation controller that has

199
00:13:20,580 --> 00:13:27,170
to happen in the main thread but Touch ID happens on a background thread.

200
00:13:27,210 --> 00:13:32,100
So for pushing the view controller we need to actually push this up onto the main thread and we can

201
00:13:32,100 --> 00:13:34,330
do that by calling dispatch.

202
00:13:34,350 --> 00:13:38,310
Q Dot main number main thread.

203
00:13:38,340 --> 00:13:45,270
Async and it's going to asynchronously push the note on the main thread because UI updates like that

204
00:13:45,300 --> 00:13:46,490
need to happen on the main thread.

205
00:13:46,500 --> 00:13:51,360
Otherwise your app gets really sluggish and it might take 15 seconds to even push that view controller

206
00:13:51,840 --> 00:13:55,180
which is a terrible experience and really memory inefficient.

207
00:13:55,500 --> 00:14:03,030
But let's say that the lock status is not locked if it's already unlocked or else we can call push note

208
00:14:03,420 --> 00:14:06,350
for index path and it'll just push the note.

209
00:14:06,360 --> 00:14:07,510
Very very cool.

210
00:14:07,710 --> 00:14:14,510
So if I have actually unlocked my note I've changed the lock status if I return back to my table view

211
00:14:14,850 --> 00:14:21,350
I should be able to go ahead and actually see that it's unlocked the lock should no longer be there.

212
00:14:21,420 --> 00:14:22,690
I want to test this.

213
00:14:22,710 --> 00:14:29,640
So we basically it's just just in review we have evaluated the policy for touch ID and we've handled

214
00:14:29,730 --> 00:14:30,350
any errors.

215
00:14:30,360 --> 00:14:34,190
If there is no touch ID available if there is no touch I.D. sensor.

216
00:14:34,350 --> 00:14:40,170
If we fail if there's an error if the user cancels whatever we are handling that problem either by showing

217
00:14:40,170 --> 00:14:43,620
an alert or completing as false which is very cool.

218
00:14:43,620 --> 00:14:49,660
So let's build this and let's go ahead and see how we did it's opening.

219
00:14:50,000 --> 00:14:54,180
If we if we select a node it should just push the note beautiful.

220
00:14:54,270 --> 00:14:57,010
If I select a note watch what happens.

221
00:14:57,060 --> 00:14:58,650
No identities are enrolled.

222
00:14:58,650 --> 00:15:02,540
Now this will not show up on a device with touch ID.

223
00:15:02,550 --> 00:15:08,100
This is only happening because we're in the simulator so go ahead and head into hardware touch I.D.

224
00:15:08,310 --> 00:15:11,120
and you're going to enroll the touch ID device.

225
00:15:11,130 --> 00:15:11,710
OK.

226
00:15:12,030 --> 00:15:18,750
Now you can click on a cell boom and it'll say Touch ID and there is localized reason our app uses Touch

227
00:15:18,750 --> 00:15:21,560
ID slash face ID to secure your notes.

228
00:15:21,570 --> 00:15:27,180
Now what you can do is you can go to a hardware Touch ID matching touch or non-matching touch.

229
00:15:27,180 --> 00:15:31,470
Now if you have the map book with touch bar you might notice down on the touch bar theres also a little

230
00:15:31,470 --> 00:15:32,790
fingerprint icon.

231
00:15:32,790 --> 00:15:34,700
You can tap that to make a matching touch.

232
00:15:34,710 --> 00:15:39,480
But for now lets select matching touch and see what happens.

233
00:15:39,570 --> 00:15:40,850
It unlock the note.

234
00:15:40,860 --> 00:15:44,470
It pushed the view controller and now it's unlocked.

235
00:15:44,610 --> 00:15:46,990
Let's do a non-matching touch to see what happens.

236
00:15:47,010 --> 00:15:53,250
So we go in we select non-matching touch and it cancels out it says error.

237
00:15:53,380 --> 00:15:58,570
Now you know what I have done this on a physical device and it does not close like that I believe this

238
00:15:58,570 --> 00:16:06,010
is a bug with the simulator because what we're doing is if we have if we evaluate policy and we get

239
00:16:06,010 --> 00:16:11,860
an error we're supposed to show an alert saying hey that didn't work and it doesn't show up on the simulator

240
00:16:12,040 --> 00:16:13,930
but it does show up in a physical device.

241
00:16:13,930 --> 00:16:16,190
So that's a weird bug that I have discovered.

242
00:16:16,390 --> 00:16:19,240
But if we do a matching touch we're good.

243
00:16:19,240 --> 00:16:19,900
We have our note.

244
00:16:19,900 --> 00:16:24,890
We've unlocked it and now the lock status is also set to unlock so we can see it.

245
00:16:24,970 --> 00:16:26,910
Now let's go ahead let's try to lock a note.

246
00:16:26,980 --> 00:16:29,010
If I push lock it locks it.

247
00:16:29,020 --> 00:16:31,650
It says this notice is locked unlock to read.

248
00:16:31,960 --> 00:16:34,600
And let's try to unlock them again.

249
00:16:34,760 --> 00:16:39,510
And it asks for touch ID I'm going to push my touch ID button there and it's unlocked.

250
00:16:39,510 --> 00:16:41,040
Guys this is amazing.

251
00:16:41,050 --> 00:16:45,990
Now you're probably wondering OK great That's touch ID but what about face Id let me quit this simulator.

252
00:16:46,030 --> 00:16:51,200
Let me run it on an iPhone X simulator or iPhone 10 simulator whichever you want to call it.

253
00:16:51,580 --> 00:16:53,810
And let's pull it up.

254
00:16:53,830 --> 00:16:55,120
Here we go.

255
00:16:55,150 --> 00:16:56,350
It's kind of hard to move.

256
00:16:56,350 --> 00:17:03,910
It's a little bit buggy in X cotinine sadly takes a little bit of finicking to get it to move around

257
00:17:03,910 --> 00:17:05,910
on the screen the way you want.

258
00:17:05,950 --> 00:17:09,410
Let's see if I can move it looks like it's stuck.

259
00:17:09,410 --> 00:17:10,790
Shrinking it down a little bit.

260
00:17:10,790 --> 00:17:11,830
Let's see if we can.

261
00:17:11,850 --> 00:17:12,470
OK beautiful.

262
00:17:12,470 --> 00:17:13,370
Got it.

263
00:17:13,370 --> 00:17:16,040
So here's our app looks really really amazing.

264
00:17:16,040 --> 00:17:21,770
If I tap on secure notes it'll say by amatory is not available on this device.

265
00:17:21,800 --> 00:17:25,490
This is a current bug in the X code release.

266
00:17:25,490 --> 00:17:28,380
This is the release of X code 9 from the App Store.

267
00:17:28,430 --> 00:17:33,710
It's a bug and I've done my research on the Apple developer forums and they said Touch ID and face ID

268
00:17:33,710 --> 00:17:35,440
should be able to be accessed.

269
00:17:35,450 --> 00:17:41,180
So if we go to face ID we can enroll face ID we can select it but it still tells us that by on a tree

270
00:17:41,180 --> 00:17:43,150
is not available on this device.

271
00:17:43,160 --> 00:17:48,230
Even if I can roll it on and roll it and enroll it it's going to tell us that it's not available but

272
00:17:48,800 --> 00:17:53,840
in a future update to X code base ID will work straight out of the box.

273
00:17:53,850 --> 00:17:56,000
OK very cool stuff.

274
00:17:56,300 --> 00:18:03,290
You can do all kinds of fun stuff with Touch ID securing content persisting log in for an account like

275
00:18:03,290 --> 00:18:09,050
my bank for instance once I log in I setup Touch ID and when I go back and I don't have to log in I

276
00:18:09,050 --> 00:18:12,650
can just use my thumbprint to secure my account which is very cool.

277
00:18:12,650 --> 00:18:19,100
So guys you know what our app is now finished we can successfully authenticate we can handle errors

278
00:18:19,100 --> 00:18:23,420
we can lock unlock notes and update our table view all in one.

279
00:18:23,420 --> 00:18:24,850
This is amazing.

280
00:18:24,860 --> 00:18:29,510
So in the next video I'm going to give you a challenge to make this app even better.

281
00:18:29,510 --> 00:18:31,030
There's some really cool stuff you can do.

282
00:18:31,040 --> 00:18:33,440
So let's head over to the next video for you challenge.
