Everybody what's going on this is Caleb with Dev slopes dot com.
And in this video get excited we're going to start using Touch I.D. and face I.D. So pull open your
project and we're going to write a function called authenticate biometrics and that's basically going
to allow us to present our Touch ID pop up and authenticate with our thumb then based on either success
or failure.
We're going to be able to do something and unlock our notes it's very very cool.
So let's go ahead and let's first import a framework called local authentication.
So go ahead and type import local authentication like so and now we have access to all the cool Touch
ID stuff.
So go ahead and write a function down here called phunk authenticates bio metrics.
All right.
And what we're actually going to do is we're going to use a completion handler to determine when we're
done.
So go ahead and type completion and make sure that it's escaping.
And what we're going to do is we're going to pass it a function and we're going to return void which
is like an empty function where we're not returning anything but what we can do is we can actually pass
in a boolean to this function.
Whenever we are finished ok and that we can use that to determine whether we authenticated successfully
or not.
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
for local authentication context.
So create that like so let my context equals a context and instantiate it.
Now in L.A. context basically handles all of the local authentication stuff.
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
et cetera et cetera.
And what we can also do here is we can also set up the localized reason string we can type let my localized
reason string.
OK.
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
Touch ID slash face I.D. to secure your notes just give a reason for why your app needs to use those
services.
And we're also going to create a variable that can be used to hold whatever errors we might receive.
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
mark at the end because it is optional.
We might not get in there.
And the reason they're using an s ere is because it has a property called code and we can pull out the
air for a particular error code.
So now what we're going to do is we're going to use a property as part of a context called can evaluate
policy and what that means is we're checking to see.
Can our device actually evaluate Touch ID.
Does it have a sensor because maybe you're building this app on an iPhone 5 without a touch I.D. sensor.
And in that case we're going to present an error.
So go ahead and say if my context DOT can evaluate policy.
Now what is our policy that's already built into local authentication so go ahead and put a dot and
we're going to say L.A. policy.
Well the name is device owner authentication with biometrics.
OK.
So that's what we're going to say.
If we can evaluate a policy with biometrics or with a touch I.D. sensor that is good to go.
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.
OK.
Now we can do is we can go ahead and pass in some curly brackets if it returns True.
OK.
Because that's what this function returns we're going to go ahead and call my contex dot evaluate policy
and what this is going to do is it's going to actually evaluate our device owner authentication with
biometrics so if we can.
Meaning if we have the sensor then we want to evaluate the device with biometrics.
Now the localized reason we already created my localized reason string.
That's what's going to pop up saying hey why are you why are you using touch ID.
And the reply is going to either have a Boolean for success or failure and an error.
So go ahead and press enter on the completion handler there and just call this success for the error.
I'm going to name it.
Evaluate error because that's what it is it's an error with evaluation.
Maybe we missed our thumb.
OK.
That's going to present an error.
So if successful meaning if success because that's the name of our property if success we're going to
call completion OK from our completion handler and we're going to pass in true because we are done we
successfully authenticate it.
But if there was an error meaning else now what we're going to do is we're going to take our evaluate
in error.
We're going to go ahead and use guard left to pull out the localized description because it is optional.
And then we should present this alert on the screen.
So go ahead and type guard let maybe evaluate evaluate error string equals evaluate air dot localized
description and as you can see that is optional.
We're going to go ahead and call.
Else return meaning if there is no error just return.
But if we're not successful then we definitely have an error.
So we now have an evaluate error string and this is where we want to present an alert.
So let's create the function to present an alert now below authenticate biometrics.
Go ahead and call or or type phunk show alert.
And we want to pass in a message so show alert with message.
OK.
And use an internal parameter of message because that just makes more sense.
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
and a UI alert action and pass in the proper data.
So go ahead and call that alert.
DC equals UI alert controller.
And if we pass in one with a title message and style we're good to go.
Now the title we're just going to say error the message is going to be the message and the preferred
style is going to be alert.
OK like a pop up alert on our screen.
Now we need to go ahead and set an action so that we can just tap OK and dismiss it.
So go ahead and type let action equals UI alert action and go ahead and give it a title style and handler.
Now the title is going to just say ok.
Whoops.
As a string.
OK.
And that's what the button will display.
Now go ahead and for the style it's just going to be default.
And for the handler This is where we're going to go ahead and just pass in nil because we don't care
what happens when we're done.
We just want to dismiss it.
So go ahead and call alert Visi and add action.
OK we're going to pass in that action like so and then we're going to go ahead and present alert VC
like so we want it to be animated and pretty and nice and to completion we want to be nil.
All right.
Very cool.
So now what we can do is we can call show alert with message and we can pass in our evaluate error string.
Now of course if we were not successful we should say completion is false right.
So let's do that because we did not successfully complete our authentication.
So that's great.
That means we're successful we complete otherwise we're not successful.
We don't complete.
But what if for some reason we can't actually use touch ID.
Right.
That's an error.
So we should say else like so and now we need to do an authentication error like if we can't even authenticate
that's where our off air is going to come from.
So go ahead and call guard left and we'll say authentic.
Well it's just too Auth. error string that's going to be equal to off air.
Localized description.
Else we're just going to return.
All righty.
So we've got an airstrip now for authentication like if we can't even authenticate.
We need to do something about that.
So go ahead and call show alert and we're going to pass in the on air string.
OK.
That will present an alert and show what the issue is.
Now you know what I am noticing we are in a closure here.
Evaluate policy so we're going to need to call self show alert and self-doubt show alert here as well
because if I build it it would yell at us for that.
But it's going to give us another problem here cannot convert value of type and as error to expected
argument type and error pointer.
Oh you know what.
OK.
That's because we're passing in an optional value here.
We need to use an ampersand right before that and that makes this an out.
This gives it in our capabilities meaning if there's an error it's going to just be returned to this
is variable.
For us to use.
So go ahead and put an and sign there at the beginning and then that air can be passed back to the variable
off error from the function.
Pretty cool.
So then of course if there's an error we present the alert and we're going to say completion is false
meaning we did not successfully authenticate.
All right.
Now of course this is great.
But what if we're on maybe a version of IOS that is not going to allow us to use touch ID.
IOS 8 is where Touch I.D. became possible.
What if our app is run on iOS 7 that's going to create problems for us.
So let's go ahead and let's make sure that that iOS version is available.
And to do that we can just say if pound sign available wups.
And as you can see you can pass in a platform here.
I'm going to say I Os eight point zero.
OK.
And you know what.
Mac OS also can use Touch ID so if this app were to be a multi-platform app you could also do Mac OS
ten point twelve point one.
That's the first version that was accessible with Touch ID and then at the end you're going to put a
little pound sign and that's going to say anything else that does not except Touch ID.
OK so if we even have it available we're going to go ahead and do all of this authentication.
OK so go ahead and cut and paste it in.
But if we don't have Touch ID available we should also be saying that completion was false because we
couldn't authenticate if we don't have Touch ID.
Now go ahead and say completion false.
So now what we're doing is we're authenticating with biometrics we're using our L.A. context to check
do we have a touch I.D. sensor.
If yes we evaluate if we're successful we pass completion is true if we're not successful we show an
alert and we say completion is false.
If we can't even value it the policy will show an authentication error message and present it then return
the completion as false.
If we don't even have access to any of this we're going to go ahead and complete false.
Pretty cool.
So now we need to think what are we going to do here to actually present what we need what we're going
to do actually is we're going to go ahead and not just simply push the note but we're only going to
push the note if we are successful otherwise we'll present an error.
So let's go ahead and let's make sure that our note that we select is is locked.
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
the item at the index path Roe that we selected lock status is equal to locked.
That means we need to authenticate with biometrics so if the status is locked go ahead and call authenticate
biometrics push enter on the completion handler and say Ophth and hated authenticated and if properly
authenticated what we're going to do is we're going to go ahead and say notes array and we're going
to access that same note what's an index path dot row.
And we're going to go ahead and change its lock status to now be unlocked so we can use lock status
flipper and we can pass in the same thing.
OK.
Notes array index path that row lock status.
And you know what to make this a little more pretty.
I'm going to go ahead and just go ahead and say let lock status and just set that to be equal to this
so that I can just pass in that as a constant here so I don't have to duplicate my code twice.
So I have now set the lock status with our lock status flipper.
It's now unlocked.
And what I can do is now I can push the note onto the view controller.
So what I can do is I can say self.
Push note for index path and I can pass in the index path.
Pretty cool stuff.
But the problem is that when you actually push a controller onto a UI navigation controller that has
to happen in the main thread but Touch ID happens on a background thread.
So for pushing the view controller we need to actually push this up onto the main thread and we can
do that by calling dispatch.
Q Dot main number main thread.
Async and it's going to asynchronously push the note on the main thread because UI updates like that
need to happen on the main thread.
Otherwise your app gets really sluggish and it might take 15 seconds to even push that view controller
which is a terrible experience and really memory inefficient.
But let's say that the lock status is not locked if it's already unlocked or else we can call push note
for index path and it'll just push the note.
Very very cool.
So if I have actually unlocked my note I've changed the lock status if I return back to my table view
I should be able to go ahead and actually see that it's unlocked the lock should no longer be there.
I want to test this.
So we basically it's just just in review we have evaluated the policy for touch ID and we've handled
any errors.
If there is no touch ID available if there is no touch I.D. sensor.
If we fail if there's an error if the user cancels whatever we are handling that problem either by showing
an alert or completing as false which is very cool.
So let's build this and let's go ahead and see how we did it's opening.
If we if we select a node it should just push the note beautiful.
If I select a note watch what happens.
No identities are enrolled.
Now this will not show up on a device with touch ID.
This is only happening because we're in the simulator so go ahead and head into hardware touch I.D.
and you're going to enroll the touch ID device.
OK.
Now you can click on a cell boom and it'll say Touch ID and there is localized reason our app uses Touch
ID slash face ID to secure your notes.
Now what you can do is you can go to a hardware Touch ID matching touch or non-matching touch.
Now if you have the map book with touch bar you might notice down on the touch bar theres also a little
fingerprint icon.
You can tap that to make a matching touch.
But for now lets select matching touch and see what happens.
It unlock the note.
It pushed the view controller and now it's unlocked.
Let's do a non-matching touch to see what happens.
So we go in we select non-matching touch and it cancels out it says error.
Now you know what I have done this on a physical device and it does not close like that I believe this
is a bug with the simulator because what we're doing is if we have if we evaluate policy and we get
an error we're supposed to show an alert saying hey that didn't work and it doesn't show up on the simulator
but it does show up in a physical device.
So that's a weird bug that I have discovered.
But if we do a matching touch we're good.
We have our note.
We've unlocked it and now the lock status is also set to unlock so we can see it.
Now let's go ahead let's try to lock a note.
If I push lock it locks it.
It says this notice is locked unlock to read.
And let's try to unlock them again.
And it asks for touch ID I'm going to push my touch ID button there and it's unlocked.
Guys this is amazing.
Now you're probably wondering OK great That's touch ID but what about face Id let me quit this simulator.
Let me run it on an iPhone X simulator or iPhone 10 simulator whichever you want to call it.
And let's pull it up.
Here we go.
It's kind of hard to move.
It's a little bit buggy in X cotinine sadly takes a little bit of finicking to get it to move around
on the screen the way you want.
Let's see if I can move it looks like it's stuck.
Shrinking it down a little bit.
Let's see if we can.
OK beautiful.
Got it.
So here's our app looks really really amazing.
If I tap on secure notes it'll say by amatory is not available on this device.
This is a current bug in the X code release.
This is the release of X code 9 from the App Store.
It's a bug and I've done my research on the Apple developer forums and they said Touch ID and face ID
should be able to be accessed.
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
is not available on this device.
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
in a future update to X code base ID will work straight out of the box.
OK very cool stuff.
You can do all kinds of fun stuff with Touch ID securing content persisting log in for an account like
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
can just use my thumbprint to secure my account which is very cool.
So guys you know what our app is now finished we can successfully authenticate we can handle errors
we can lock unlock notes and update our table view all in one.
This is amazing.
So in the next video I'm going to give you a challenge to make this app even better.
There's some really cool stuff you can do.
So let's head over to the next video for you challenge.