Swift Note

兴趣是最好的老师

Touch ID 验证的时机以及一些小坑

在 app 中启用 Touch ID 其实很简单,无非是使用文档中的方法,但验证的时机却有点儿讲究。

基本用法

应用内本地身份验证,比如像微信的指纹支付,就很简单了,用官方的方法就行了,下面是苹果开发文档中的方法:

let myContext = LAContext()  
let myLocalizedReasonString = <#String explaining why app needs authentication#>

var authError: NSError? = nil  
if #available(iOS 8.0, OSX 10.12, *) {  
    if myContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &authError) {
        myContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString) { (success, evaluateError) in
            if (success) {
                // User authenticated successfully, take appropriate action
            } else {
                // User did not authenticate successfully, look at error and take appropriate action
            }
        }
    } else {
        // Could not evaluate policy; look at authError and present an appropriate message to user
    }
} else {
    // Fallback on earlier versions
}

但如果要在进入app时验证,就需要在所有 view 出现之前调用,这个时候需要在 appDelegate 中来实现了。而调用的地方,通常在三个方法中: didFinishLaunchingWithOptionsapplicationWillEnterForegroundapplicationDidBecomeActive,关于这几个方法的调用顺序,请参考 UIApplicationDelegate 中各方法的调用顺序 。通过测试,把验证放到 applicationDidBecomeActive中是最方便的,但,你不嫌麻烦的话,就需要同时放入前面两个中。

小坑 1

但是,验证方法在 applicationDidBecomeActive 中会有一个问题,就是验证会 loop 掉,也就是会一直验证,卡在 Touch ID 验证的界面,从而进不去 app !

这个时候,我们可以添加一个标记,默认是 false 验证成功后,改为 true

var isLocked:Bool = false  
func applicationDidBecomeActive(application: UIApplication) {  
    if isLocked == false{
        authorTouchID()
    }else{
        print("not unlocked")
    }
}

然后在 authorTouchID 方法中,当验证成功,重写 isLocked 变量的值就好了

添加背景

Touch ID 默认背景是半透明的黑色,这个背景并不能完整遮盖内容 view ,这个时候我们就需要添加一个背景层的 view,比如,模糊背景。

小坑 2

但是默认的话,验证成功后,要消除掉这个 view,而简单的 removeFromSuperview 并不会直接移除掉这个 view,大概要等个 3-10 秒钟,这个时候,控制台通常还会爆出一些警告。

解决方法就是,把 removeFromSuperviewdispatch_async 放回主线程:

dispatch_async(dispatch_get_main_queue()){  
    self.isLocked = true
    self.blurView.removeFromSuperview()
}

完整的 authorTouchID 方法:

func authorTouchID(){  
        let context: LAContext! = LAContext()

        blurView.effect = blurEffect
        blurView.opaque = false

        if let frame = window?.frame {
            blurView.frame = frame
        }
        self.window?.addSubview(blurView)
        if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthentication, error: nil) {

            context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: "enheng") { (success, authenticationError) in
                if success{
                    print("yes")
                    dispatch_async(dispatch_get_main_queue()){
                        self.isLocked = true
                        self.blurView.removeFromSuperview()
                    }

                }else{
                    let theError:LAError = authenticationError as! LAError
                    switch theError{
                    case .AuthenticationFailed :
                        print("Authentication Failed")
                        break
                    case .UserCancel :
                        print("User Canceled")
                        break
                    case .TouchIDNotAvailable :
                        print("TouchID not avaliable")
                        break
                    default :
                        print("error")
                        break
                    }
                }
            }
        } else {
            print("can't use TouchID")
        }
    }

神飞

没有什么能够阻挡,我对自由的向往