How to use TouchID using Swift?

2020-06-19 03:28发布

问题:

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) {
        }
    }
}

回答1:

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

}



回答2:

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.



回答3:

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.



回答4:

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")
        }
    }


回答5:

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



回答6:

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")
                }

            })
        }

    }
}