Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) {
        }
    }
}
like image 543
user3785085 Avatar asked Jun 28 '14 07:06

user3785085


2 Answers

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.
}

}

like image 132
macshome Avatar answered Oct 09 '22 21:10

macshome


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.

like image 40
Dylan Gattey Avatar answered Oct 09 '22 21:10

Dylan Gattey