2015-12-13 43 views
1

我使用Swift实现了touchID的登录可能性。 以下内容:当应用程序启动时,有一个登录屏幕和一个touchID弹出窗口 - 工作正常。问题发生在应用程序从后台加载时:如果尚未超过特定的时间范围,我希望touchID弹出窗口在登录屏幕上出现 - 但是这次我希望touchID转到上次显示的视图该应用程序进入后台。 (即,如果用户想要取消touchID,则在其下面存在登录屏幕,然后他可以通过密码进行认证,如果touchID认证成功,则登录屏幕应该被解除,并且如果touchID认证成功,则将其导向最后显示的视图最后显示的视图。) 我真的尝试了一切,并寻找答案 - 没有什么能帮助我。这里是我的代码:如何处理从后台加载应用程序的touchID Swift

override func viewDidLoad() { 
    super.viewDidLoad() 
    //notify when foreground or background have been entered -> in that case there are two methods that will be invoked: willEnterForeground and didEnterBackground 
    let notificationCenter = NSNotificationCenter.defaultCenter() 
    notificationCenter.addObserver(self, selector: "willEnterForeground", name:UIApplicationWillEnterForegroundNotification, object: nil) 
    notificationCenter.addObserver(self, selector: "didEnterBackground", name: UIApplicationDidEnterBackgroundNotification, object: nil) 
    password.secureTextEntry = true 
    if (username != nil) { 
     username.text = "bucketFit" 
    } 
    username.delegate = self 
    password.delegate = self 

    if let alreadyShown : AnyObject? = def.objectForKey("alreadyShown") { 
     if (alreadyShown == nil){ 
      authenticateWithTouchID() 
     } 
    } 
} 

willEnterForeground:

func willEnterForeground() { 
    //save locally that the guide already logged in once and the application is just entering foreground 
    //the variable alreadyShown is used for presenting the touchID, see viewDidAppear method 
    def.setObject(true, forKey: "alreadyShown") 
    if let backgroundEntered : AnyObject? = def.objectForKey("backgroundEntered") { 
     let startTime = backgroundEntered as! NSDate 
     //number of seconds the app was in the background 
     let inactivityDuration = NSDate().timeIntervalSinceDate(startTime) 
     //if the app was longer than 3 minutes inactiv, ask the guide to input his password 
     if (inactivityDuration > 2) { 
      showLoginView() 
     } else { 
      def.removeObjectForKey("alreadyShown") 
      showLoginView() 
     } 
    } 
} 

authenticateWithTouchID():

func authenticateWithTouchID() { 
    let context : LAContext = LAContext() 
    context.localizedFallbackTitle = "" 
    var error : NSError? 
    let myLocalizedReasonString : NSString = "Authentication is required" 
    //check whether the iphone has the touchID possibility at all 
    if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) { 
     //if yes then execute the touchID and see whether the finger print matches 
     context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString as String, reply: { (success : Bool, evaluationError : NSError?) -> Void in 
      //touchID succeded -> go to students list page 
      if success { 
       NSOperationQueue.mainQueue().addOperationWithBlock({() -> Void in 
        self.performSegueWithIdentifier("studentsList", sender: self) 
       }) 
      } else { 
       // Authentification failed 
       print(evaluationError?.description) 
       //print out the specific error 
       switch evaluationError!.code { 
       case LAError.SystemCancel.rawValue: 
        print("Authentication cancelled by the system") 
       case LAError.UserCancel.rawValue: 
        print("Authentication cancelled by the user") 
       default: 
        print("Authentication failed") 
       } 
      } 
     }) 
    } 
} 

shouldPerformSegueWithIdentifier:

override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool { 
    if (false) { //TODO -> username.text!.isEmpty || password.text!.isEmpty 
     notify("Login failed", message: "Please enter your username and password to proceed") 
     return false 
    } else if (false) { //TODO when backend ready! -> !login("bucketFit", password: "test") 
     notify("Incorrect username or password", message: "Please try again") 
     return false 
     //if the login page is loaded after background, dont proceed (then we need to present the last presented view on the stack before the app leaved to background) 
    } else if let alreadyShown : AnyObject? = def.objectForKey("alreadyShown") { 
     if (alreadyShown != nil){ 
      //TODO check whether login data is correct 
      dismissLoginView() 
      return false 
     } 
    } 

    return true 
} 

在此先感谢您。

回答

1

你可以做的是创建一个AuthenticationManager。该经理将是一个共享实例,用于跟踪是否需要更新认证。您可能还想要包含所有auth方法。

class AuthenticationManager { 
    static let sharedInstance = AuthenticationManager() 
    var needsAuthentication = false 
} 

在AppDelegate中:

func willEnterForeground() { 
    def.setObject(true, forKey: "alreadyShown") 
    if let backgroundEntered : AnyObject? = def.objectForKey("backgroundEntered") { 
     let startTime = backgroundEntered as! NSDate 
     //number of seconds the app was in the background 
     let inactivityDuration = NSDate().timeIntervalSinceDate(startTime) 
     //if the app was longer than 3 minutes inactiv, ask the guide to input his password 
     if (inactivityDuration > 2) { 
      AuthenticationManager.sharedInstance.needsAuthentication = true 
     } 
    } 
} 

然后,子类的UIViewController与名为SecureViewController视图控制器。在这个子类

override fun viewDidLoad() { 
    super.viewDidLoad() 
    if (AuthenticationManager.sharedInstance().needsAuthentication) { 
    // call authentication methods 
    } 
} 

覆盖viewDidLoad中()现在,让那些需要SecureViewController的认证子类所有的视图控制器。

相关问题