2015-12-13 85 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的認證子類所有的視圖控制器。

相關問題