Hi I’m experiencing a strange behavior I really don’t understand.
I present a touch ID identification to the user and if he’s authorized I call a [self performSegueWithIdentifier: @"callCustomSegue" sender:self]; inside the block in this way:
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
[self performSegueWithIdentifier: @"callCustomSegue" sender:self];
Then the app stops for several seconds (at least 3-4) then next ViewController is presented.
The perform called by “callCustomSegue” does this:
- (void) perform {
src = (UIViewController *) self.sourceViewController;
dst = (UIViewController *) self.destinationViewController;
[src.view addSubview:dst.view];
}
I don’t understand what’s happening between the identification on touch ID and the performSegueWithIdentifier and why the app stops.
If I bypass the touch ID and just call the performSegueWithIdentifier works immediately as I would expect.
If I put in the touch ID block:
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:myLocalizedReasonString
reply:^(BOOL success, NSError *error) {
if (success) {
authenticated = YES;
[self showMessage:@"Authentication is successful" withTitle:@"Success"];
}
where showMessage does this:
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* cancel = [UIAlertAction
actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
if (authenticated) {
[self performSegueWithIdentifier: @"callCustomSegue" sender:self];
}
if (!authenticated) {
[self touchID];
}
}];
after tapping OK the next ViewController is called immediately.
So the question is: why I can’t call performSegue within the touch ID block and get an immediate response?
Any idea where I’m wrong?
Thank you so much.
You should perform all UI related activities on the main queue. The reply
block for the touchID process is not guaranteed to be executing on the main queue. In fact you can almost guarantee that it won't be.
You should have -
if (success) {
authenticated = YES;
dispatch_async(dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier: @"callCustomSegue" sender:self];
});