User クラス内に次の関数があります。
// Attempts to log in the user, given a password.
// Sets user's loginSuccessful to true upon successful login, false otherwise.
// If failed login, user's loginFailedMessage is also updated.
func attemptLogin(password:String) {
// create a new NSURL pointing to the PHP login script
let url = NSURL(string: loginScriptLocation)
// create a new NSMutableURLRequest of type POST
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
// add POST string with username and password to request
let postString = "username=\(self.username)&password=\(password)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
// send the request and get the JSON results
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
// if there is an error with the request, print it
if error != nil {
println("error: \(error)")
return
}
// otherwise, go ahead and parse JSON results
var err:NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
if let parseJSON = json {
var resultValue = parseJSON["status"] as? String
if resultValue! == "success" {
// login successful
self.loginSuccessful = true
}
else {
// login not successful
self.loginSuccessful = false
self.loginFailedMessage = parseJSON["message"] as! String
}
}
}
task.resume()
}
問題は...
ログイン UIButton の IBAction がトリガーされると、LoginViewController でこの attemptsLogin() 関数が呼び出されます。この IBAction 関数内で試行ログイン() が呼び出された後、それに続くステートメントは、ユーザーの loginSuccessful 変数が true に設定されているかどうかを確認します。true の場合、別のビュー コントローラーにセグエする (ユーザーをログインさせる) ことを意味します。false の場合、エラー メッセージが表示されます。
しかしもちろん、loginSuccessful が true に設定されているかどうかを確認しているとき (attemptLogin() を呼び出した後) に、NSURLSession がまだその時点に達していないため、これは機能しません。NSURLSession に「クロージャー」または「完了ハンドラー」を追加する必要があるように感じますが、StackOverflow で例を精査した後でも、その方法が本当にわかりません。私は iOS プログラミングと非同期/同期メソッドの超初心者なので、判断しないでください。
既存の attemptsLogin() 関数を変更して、NSURLSession が完了したときに何かをトリガーできるようにするにはどうすればよいですか (ビュー コントローラーの別の画面に移動したり、エラーが発生した場合にユーザーにアラートを表示したりできます)。
これは私の LoginViewController のコードです:
// Triggered when login button is tapped
// Attempts to log in a user with username and password typed in.
// Successful login -> takes user to Explore screen
// Failed login -> shows alert message with error
@IBAction func loginButtonTap(sender: UIButton) {
if (usernameTextField.text.isEmpty || passwordTextField.text.isEmpty) {
// show alert saying missing required field
}
else {
// attempt login
self.myUser.setUsernameWithoutPushingToDatabase(self.usernameTextField.text)
self.myUser.attemptLogin(self.passwordTextField.text)
if (self.myUser.didLoginSuccessfully()) {
// login successful, segue to Explore screen
self.performSegueWithIdentifier("loginToExploreSegue", sender: self)
}
else {
// login failed, display alert with error message
var incorrectPassAlert = UIAlertController(title: "Login Failed", message: self.myUser.loginFailedMessage, preferredStyle: UIAlertControllerStyle.Alert)
incorrectPassAlert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
self.presentViewController(incorrectPassAlert, animated: true, completion: nil)
}
}
}