在 Swift 中向我的 NSURLSession 添加完成处理程序
Adding a completion handler to my NSURLSession in Swift
我在用户 class 中有以下功能:
// 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 被触发时,这个 attemptLogin() 函数在我的 LoginViewController 中被调用。在这个 IBAction 函数中调用 attemptLogin() 之后,它后面的语句会检查用户的 loginSuccessful 变量是否已设置为 true。如果为真,则表示转到不同的视图控制器(让用户登录);如果为 false,则表示显示错误消息。
但这当然不起作用,因为当我检查 loginSuccessful 是否已设置为 true 时(在我调用 attemptLogin() 之后),我的 NSURLSession 还没有达到这一点。我觉得我需要在我的 NSURLSession 中添加一个 "closure" 或 "completion handler",但即使在搜索 Whosebug 以获取示例后,我真的不明白该怎么做。我是 iOS 编程和 asynchronous/synchronous 方法的初学者,所以不要评判我!
我如何修改我现有的 attemptLogin() 函数,以便在 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)
}
}
}
你是对的,你希望将闭包传递给 attemptLogin
尝试这样的事情
func attemptLogin(password:String, completion: (Bool) -> Void)
然后
if resultValue! == "success" {
// login successful
completion(true)
}
else {
completion(false)
}
最后你必须在 loginButtonTap
中创建闭包
self.myUser.attemptLogin(self.passwordTextField.text, completion: (successful: Bool) -> Void) {
if successful {
// login was good
} else {
// login was bad
}
})
您的 attempLogin 函数应该采用如下所示的完成处理程序:
func attemptLogin(password:String, completionHandler: (success: Bool, message: String) -> ()) { your code }
在该方法中,您应该将结果数据传递给该完成处理程序:
if resultValue! == "success" {
// login successful
self.loginSuccessful = true
completionHandler(success: True, message: "Login Successful.")
}
else {
// login not successful
self.loginSuccessful = false
self.loginFailedMessage = parseJSON["message"] as! String
completionHandler(success: False, message: loginFailedMessage)
}
最后,您可以像这样调用 attempLogin:
self.myUser.attemptLogin(self.passwordTextField.text, {(success: Bool, message: String) -> () in
if(success) {
//do something
}
else {
// do something or print message etc.
}
})
我在用户 class 中有以下功能:
// 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 被触发时,这个 attemptLogin() 函数在我的 LoginViewController 中被调用。在这个 IBAction 函数中调用 attemptLogin() 之后,它后面的语句会检查用户的 loginSuccessful 变量是否已设置为 true。如果为真,则表示转到不同的视图控制器(让用户登录);如果为 false,则表示显示错误消息。
但这当然不起作用,因为当我检查 loginSuccessful 是否已设置为 true 时(在我调用 attemptLogin() 之后),我的 NSURLSession 还没有达到这一点。我觉得我需要在我的 NSURLSession 中添加一个 "closure" 或 "completion handler",但即使在搜索 Whosebug 以获取示例后,我真的不明白该怎么做。我是 iOS 编程和 asynchronous/synchronous 方法的初学者,所以不要评判我!
我如何修改我现有的 attemptLogin() 函数,以便在 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)
}
}
}
你是对的,你希望将闭包传递给 attemptLogin
尝试这样的事情
func attemptLogin(password:String, completion: (Bool) -> Void)
然后
if resultValue! == "success" {
// login successful
completion(true)
}
else {
completion(false)
}
最后你必须在 loginButtonTap
self.myUser.attemptLogin(self.passwordTextField.text, completion: (successful: Bool) -> Void) {
if successful {
// login was good
} else {
// login was bad
}
})
您的 attempLogin 函数应该采用如下所示的完成处理程序:
func attemptLogin(password:String, completionHandler: (success: Bool, message: String) -> ()) { your code }
在该方法中,您应该将结果数据传递给该完成处理程序:
if resultValue! == "success" {
// login successful
self.loginSuccessful = true
completionHandler(success: True, message: "Login Successful.")
}
else {
// login not successful
self.loginSuccessful = false
self.loginFailedMessage = parseJSON["message"] as! String
completionHandler(success: False, message: loginFailedMessage)
}
最后,您可以像这样调用 attempLogin:
self.myUser.attemptLogin(self.passwordTextField.text, {(success: Bool, message: String) -> () in
if(success) {
//do something
}
else {
// do something or print message etc.
}
})