Face ID userFallback not working in iOS swift - ios

I a implementing face ID in my iOS app. When authentication fails a alert shows containing cancel and try again buttons, cancel button works but try again button not working. How can I edit this button or to be worked try again button. When i Click on try again button nothing happens if i click on cancel button that is working and even title of cancel button also be changing but no action is applying on try again.I have tried the following code and had a lot of search on internet but nothing found.
enter image description here
func startFaceIDTest(){
attempted = true
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Identify yourself!"
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason, reply: {
successfaceID, authenticationError in
DispatchQueue.main.async {
if successfaceID {
self.success = true
} else {
self.success = false
guard let errorr = authenticationError else {return}
switch(errorr) {
case LAError.authenticationFailed:
print("Failed")
break
case LAError.userCancel:
print("User cancel")
break
case LAError.userFallback:
print("Fallback")
break
case LAError.systemCancel:
print("System cancel")
break
default:
break
}
}
}
})
} else {
if let err = error {
if #available(iOS 11.0, *) {
self.success = false
switch err.code {
case LAError.Code.biometryNotEnrolled.rawValue:
notifyUser("Your device not enrolled for biometric",
err: err.localizedDescription)
case LAError.Code.passcodeNotSet.rawValue:
notifyUser("A passcode has not been set",
err: err.localizedDescription)
case LAError.Code.biometryNotAvailable.rawValue:
notifyUser("Biometric authentication not available",
err: err.localizedDescription)
default:
notifyUser("Unknown error",
err: err.localizedDescription)
}
} else {
// Fallback on earlier versions
}
}
}
}
func notifyUser(_ msg: String, err: String?) {
let alert = UIAlertController(title: msg, message: err, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}

func bioandpasscodeAuthentication() {
let context = LAContext()
var error:NSError?
// edit line - deviceOwnerAuthentication
guard context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) else {
//showAlertViewIfNoBiometricSensorHasBeenDetected()
return
}
let reason = "Identify yourself!"
// edit line - deviceOwnerAuthentication
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
// edit line - deviceOwnerAuthentication
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason, reply: { (success, error) in
if success {
DispatchQueue.main.async {
print("Authentication was successful")
}
}else {
DispatchQueue.main.async {
//self.displayErrorMessage(error: error as! LAError )
print("Authentication was error")
}
}
})
}else {
// self.showAlertWith(title: "Error", message: (errorPointer?.localizedDescription)!)
}
}
try this code

Related

SFSpeechRecognizer fails with Error Domain=kAFAssistantErrorDomain Code=1700 on Ipad

I've a strange bug which occur only on iPad physical device, on iPhone physical device and all iPad simulators all works great, but on iPad physical device I get Error Domain=kAFAssistantErrorDomain Code=1700. How this can happen?
My code for SFSpeechRecognizer:
func requestTranscribePermissions() {
SFSpeechRecognizer.requestAuthorization { [unowned self] authStatus in
DispatchQueue.main.async {
if authStatus == .authorized {
print("Good to go!")
} else {
print("Transcription permission was declined.")
}
}
}
}
func convertAudioToText() {
if let file = audio {
print(file)
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
let request = SFSpeechURLRecognitionRequest(url: file)
request.shouldReportPartialResults = false
if (recognizer?.isAvailable)! {
recognizer?.recognitionTask(with: request) { result, error in
guard error == nil else { print("Error: \(error!)"); return }
guard let result = result else { print("No result!"); return }
self.text = result.bestTranscription.formattedString
self.performSegue(withIdentifier: "Convert", sender: nil)
print(result.bestTranscription.formattedString)
}
} else {
print("Device doesn't support speech recognition")
}
} else {
let alert = UIAlertController(title: "There's no audio", message: "No audio recorded", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"), style: .default, handler: { _ in
NSLog("The \"OK\" alert occured.")
}))
self.present(alert, animated: true, completion: nil)
}
}
Only on iPad phycal device I get:
[Utility] +[AFAggregator logDictationFailedWithError:] Error Domain=kAFAssistantErrorDomain Code=1700 "(null)"
Error: Error Domain=kAFAssistantErrorDomain Code=1700 "(null)"
I had the same error in my app.
The error was fixed updating my iphone from iOS 13.4.2 to 13.5.1 and XCode to 11.5.
Hope this help.
I had this problem on macOS and it was simply due to not requesting authorisation first.
[SFSpeechRecognizer requestAuthorization: ...]

Invalid NSError Instance

I am getting a weird message in the console after I run this code:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let pickUp = sortedPickUps[indexPath.item]
let alert = UIAlertController(title: "Delete", message: "Permanently delete your order?", preferredStyle: .alert)
let yes = UIAlertAction(title: "Yes", style: .destructive) { (actio) in
DispatchQueue.main.async {
self.pickUpController.delete(pickUp: pickUp)
self.pickUpController.deleteFirebasePickUp(pickUp: pickUp, completion: { (error) in
if let error = error {
NSLog("Error deleting pick up \(error)")
}
})
self.sortedPickUps = self.pickUpController.pickUps.sorted(by: { $0.timestamp > $1.timestamp })
self.collectionView.reloadData()
}
self.sendNotification()
}
let no = UIAlertAction(title: "No", style: .default) { (action) in }
alert.addAction(yes)
alert.addAction(no)
present(alert, animated: true, completion: nil)
}
The URLSession in the deleteFirebasePickUp looks like this
URLSession.shared.dataTask(with: request) { (data, _, error) in
if let error = error {
NSLog("Error deleting entry from server: \(error)")
DispatchQueue.main.async {
completion(error)
}
return
}
DispatchQueue.main.async {
guard let index = self.pickUps.index(of: pickUp) else {
NSLog("Something happened to the entry")
completion(NSError())
return
}
self.pickUps.remove(at: index)
completion(nil)
}
}.resume()
The app doesn't crash, and in fact does what it's supposed to do - removes the pickUp from the device and from the database. The error is error = (Error?) domain: nil - code:0
The debugger says
Something happened to the entry 2018-10-13 14:14:37.608435-0700 chute[36293:4218837] -[NSError init] called; this results in an invalid NSError instance. It will raise an exception in a future release. Please call errorWithDomain:code:userInfo: or initWithDomain:code:userInfo:. This message shown only once.
Any ideas?
Reread the debugger's message:
[NSError init] called; this results in an invalid NSError instance.
If you reread your second code block
DispatchQueue.main.async {
guard let index = self.pickUps.index(of: pickUp) else {
NSLog("Something happened to the entry")
completion(NSError()) // THIS LINE
return
}
self.pickUps.remove(at: index)
completion(nil)
}
The NSError() constructor corresponds to [NSError init], which is deprecated. You should use the init(domain:code:userInfo:) initializer instead: https://developer.apple.com/documentation/foundation/nserror/1417063-init

how to enable try Face ID again button in alert when Face ID failed to authenticate in iOS

I am using Face id in my iOS app. Be default when user fails to authenticate try again not working. I want to add callback when user click on try again.Please see my below code.I have searched a lot but nothing found about face id.
func startFaceIDTest(){
attempted = true
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Identify yourself!"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[unowned self] (successfaceID, authenticationError) in
DispatchQueue.main.async {
if successfaceID {
self.success = true
//self.unlockSecretMessage()
} else {
self.success = false
// let ac = UIAlertController(title: "Authentication failed", message: "You could not be verified; please try again.", preferredStyle: .alert)
// ac.addAction(UIAlertAction(title: "OK", style: .default))
// self.present(ac, animated: true)
}
}
}
} else {
if let err = error {
if #available(iOS 11.0, *) {
self.success = false
switch err.code {
case LAError.Code.biometryNotEnrolled.rawValue:
notifyUser("Your device not enrolled for biometric",
err: err.localizedDescription)
case LAError.Code.passcodeNotSet.rawValue:
notifyUser("A passcode has not been set",
err: err.localizedDescription)
case LAError.Code.biometryNotAvailable.rawValue:
notifyUser("Biometric authentication not available",
err: err.localizedDescription)
default:
notifyUser("Unknown error",
err: err.localizedDescription)
}
} else {
// Fallback on earlier versions
}
}
}
}

Handling Email Does not Exist Error - iOS project using swift

Here's my ResetPassword Button for my iOS application using xcode and swift:
//ResetPssword Button
#IBAction func ResetPassword(sender: AnyObject) {
if validateEmail(EmailTextField.text!) == false {
print("Enter a Valid Email Address")
let VaildMessage = "Enter an Email Address"
//Empty TextField Alert Message
self.disaplayErrorMessage(VaildMessage)
}
//Reset
else {
ref.resetPasswordForUser(EmailTextField.text) { (ErrorType) -> Void in
if ErrorType != nil {
let error = ErrorType
print("There was an error processing the request \(error.description)")
let errorMessage:String = "The Email You Entered is not Exist"
//Error Alert Message
self.disaplayErrorMessage(errorMessage)
} else {
print("Password Reset Sent Successfully")
if let Email = self.EmailTextField.text {
let successMessage = "Email Message was Sent to You at \(Email)"
//Success Alert Message
self.disaplayErrorMessage(successMessage) }
}
} //reset
} //Big Else
} //Button
//Display Alert Message With Confirmation
func disaplayErrorMessage(theMessage:String)
{
//Display alert message with confirmation.
let myAlert = UIAlertController(title: "Alert", message: theMessage, preferredStyle: UIAlertControllerStyle.Alert);
let OkAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default) {
action in
self.dismissViewControllerAnimated(true, completion: nil);
}
myAlert.addAction(OkAction);
self.presentViewController(myAlert, animated: true, completion: nil)
}
//Validate Email Function
func validateEmail(candidate: String) -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}"
return NSPredicate(format: "SELF MATCHES %#", emailRegex).evaluateWithObject(candidate)
}
I want to make an error that gives the user an alert when email does not exist in the firebase.
I did not know how to do that.
What I did, I gave the user an alert when error != nil
Is that the right way to do it?
The firebase website has a full listing of error codes
User Authentication
The pre-defined error codes provide info on pretty much all of the errors you may receive when authenticating or handling users.
ref.resetPassword({
email: EmailTextField.text!
}, function(error) {
if (error != nil) {
if let errorCode = FAuthenticationError(rawValue: error.code) {
switch (errorCode) {
case .UserDoesNotExist:
println("Handle invalid user")
case .InvalidEmail:
println("Handle invalid email")
case .InvalidPassword:
println("Handle invalid password")
default:
println("Handle default situation")
}
}
} else {
// Success!
}
}
According to FireBase doc here it may not always be a case. Don't put it as ErrorType, change it to error. It will be NSError type. Check code of the error you get like so:
if error != nil {
if error.description == "INVALID_USER" {
// show alert that user doesn't exists
} else {
// something went wrong
}
}
}

How to use TouchID using Swift?

The documentation that Apple has provided for TouchID implementation for iOS 8 is in Objective-C.
Is there a Swift version of it?
Objective-C:
- (IBAction)touchIDAvailable:(UIButton *)touchIDAvailableButton {
LAContext *context = [[LAContext alloc] init];
__block NSString *msg;
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:NSLocalizedString(#"Place your finger on the sensor", nil) reply: ^(BOOL success, NSError *authenticationError) {
if (success) {
}
}
}
Swift:
#IBAction func touchidbutton(sender: AnyObject) {
authContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: "Place your finger on the sensor"?, reply: ((success : Bool, NSError!) -> Void)?){
if (success) {
}
}
}
Here is my view controller that does these checks in Swift. While working on this I found the completion block/closure syntax in Swift to be very confusing.
Notice that some of the options changed in Beta 2 in order to give you more control over the Touch ID dialog such as disabling the fallback option or the cancel button.
// Imports
import UIKit
import LocalAuthentication
// Class Implementation
class FirstViewController: UIViewController {
// Class Properties
#IBOutlet var statusLabel : UILabel
#IBOutlet var headerString: UILabel
var authError : NSError?
var authContext = LAContext()
var statusText = ""
var alert = UIAlertController(title: "", message: "", preferredStyle: UIAlertControllerStyle.Alert)
// Class Methods
#IBAction func swiftButtonPress(sender : AnyObject) {
statusLabel.text = "Authenticating"
//Can we use local auth?
if authContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &authError) {
authContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics,
localizedReason: "I need to see if it's really you",
reply: {(success: Bool, error: NSError!) -> Void in
if success {
self.statusText = "Touch ID success!"
self.alert.title = "Success"
self.alert.message = "I knew it was you!"
} else {
self.statusText = "Touch ID failed!"
self.alert.title = "Failure"
switch error!.code {
case LAError.AuthenticationFailed.toRaw():
self.alert.message = "Authentication Failed"
case LAError.UserCancel.toRaw():
self.alert.message = "User canceled!"
case LAError.SystemCancel.toRaw():
self.alert.message = "The system canceled!"
case LAError.UserFallback.toRaw():
self.alert.message = "User request to enter passcode"
default:
self.alert.message = "Something else went wrong"
}
}
self.presentViewController(self.alert, animated: true, completion:{self.statusLabel.text = self.statusText})
})
} else {
self.statusText = "No local authentication"
alert.title = "Uh oh!"
switch authError!.code {
case LAError.TouchIDNotAvailable.toRaw():
alert.message = "No Touch ID on device"
case LAError.TouchIDNotEnrolled.toRaw():
alert.message = "No fingers enrolled"
case LAError.PasscodeNotSet.toRaw():
alert.message = "No passcode set"
default:
alert.message = "Something went wrong getting local auth"
}
self.presentViewController(self.alert, animated: true, completion: {self.statusLabel.text = self.statusText})
}
resetTouchID()
}
// Reset the system so we can go again
func resetTouchID() {
authContext = LAContext()
alert = UIAlertController(title: "", message: "", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: nil))
let passcodeDetector = SwiftPasscodeDetector()
if passcodeDetector.checkForPasscode() {
headerString.text = "Passcode Set on Device"
} else {
headerString.text = "No Passcode Set"
}
}
// Inherited Methods
override func viewDidLoad() {
super.viewDidLoad()
resetTouchID()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The API name is LAContext, and it's in the docs right here. It's pretty sparse, but it does its job. The method you probably want is
evaluatePolicy(_ policy: LAPolicy,
localizedReason localizedReason: String!,
reply reply: ((Bool, NSError!) -> Void)!)
The string argument is a subheader to display to the user, the reply is simply a callback block, and the policy currently has to be LAPolicy.DeviceOwnerAuthenticationWithBiometrics, but it appears the framework is there for other types of authentication in the future. Interesting...
Hope that helps! I tried on my phone because I was curious and it works wonderfully. Just make sure to query for ability to evaluate policy before you try to use it, in case it's on an older device.
The LAContext reference has method signatures in both Obj-C and Swift. Furthermore, if you ⌘-click on the LAContext class in your Swift code, you should be able to view the generated "header" for it in Swift.
Updated to Swift 3
static func authorizeWithTouchIDIfPossible(){
let authContext = LAContext()
var authError : NSError?
if authContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
authContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "I need to see this", reply: { (success, error) in
if success {
print("Touch ID success!")
DispatchQueue.main.async {
//Do stuff here
}
} else {
print("Touch ID failed!")
}}
);
} else {
print("No local authentication")
}
}
Found it!
The link below is from a user named Shmoopi from Github. Shmoopi made the app to test the TouchID programmed in Swift.
https://github.com/Shmoopi/Swift-Touch-ID
Swift 3.0 in:
import UIKit
import LocalAuthentication
class ViewController: UIViewController
{
#IBAction func TouchBtn(_ sender: AnyObject)
{
let context:LAContext = LAContext()
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error:nil)
{
context.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, localizedReason:"We Need Your Id", reply:{
(wasSuccessful,Error) in
if wasSuccessful
{
print("Was a Sucess")
}
else
{
print("Not Logged In")
}
})
}
}
}
Swift 5 :
import LocalAuthentication
func authenticateUser() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Identify yourself!"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[unowned self] success, authenticationError in
DispatchQueue.main.async {
if success {
print("Success!")
} else {
let ac = UIAlertController(title: "Authentication failed", message: "Sorry!", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
self.present(ac, animated: true)
}
}
}
} else {
let ac = UIAlertController(title: "Touch ID not available", message: "Your device is not configured for Touch ID.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}

Resources