2015-06-23 8 views
0

У меня есть следующие функции внутри класса User: функцииДобавление обработчика завершения моей NSURLSession в Swift

// 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() 
} 

Проблема состоит в том ...

Это attemptLogin() называется в моем LoginViewController, когда IBAction для моего входа в систему UIButton запускается. После того, как функция tryLogin() вызывается внутри этой функции IBAction, операторы, следующие за ней, проверяют, установлено ли значение переменной loginSuccessful пользователя равным true. Если значение true, оно предназначено для перехода на другой контроллер просмотра (вход в систему пользователя); если false, оно предназначено для отображения сообщения об ошибке.

Но, конечно, это не сработает, потому что когда я проверяю, установлено ли loginSuccessful значение true или нет (после вызова метода tryLogin()), моя NSURLSession еще не дошла до этой точки. Я чувствую, что мне нужно добавить «закрытие» или «обработчик завершения» в мой NSURLSession, но я действительно не понимаю, как это сделать, даже после очистки StackOverflow для примеров. Я огромный новичок в программировании на iOS и асинхронных/синхронных методах, поэтому не судите меня!

Как изменить существующую функцию tryLogin(), чтобы я мог запускать что-то, что произойдет при завершении 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) 
     } 
    } 
} 

ответ

1

Вы правы, вы хотите укупорочное быть передан 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 
    } 
}) 
+0

Спасибо за ваш ответ, но я думаю, что вы что-то пропустили. Я точно выполнил ваши инструкции и смог создать и протестировать мое приложение без ошибок, но он все еще не работает должным образом. Когда я набираю правильное имя пользователя и пароль и нажимаю кнопку входа в систему, мне сначала предъявляется предупреждение, в котором сообщается «Ошибка входа в систему». Затем я нажимаю «ОК», и только тогда я показываю правильный контроллер просмотра, который должен отображаться с моим сеансом. – dulin95

+0

Итак, в последнем блоке кода, который вы написали в своем ответе, я добавил println для каждого, если ветка печатает, с какой ветвью я ее ввел. Я смог проверить его с правильной комбинацией имени пользователя и пароля, и он прекрасно прошел успешную ветку.И если я использовал неправильное имя пользователя/пароль, оно попало в ветку else, как должно. Тем не менее, похоже, что время все еще выключено. Когда я пытаюсь перейти к другому контроллеру представления, он не будет работать с первым нажатием кнопки, но он обязательно будет работать на втором! Странно ... это как-то все еще отстает. – dulin95

+0

Смотрите мою функцию loginButtonTap() здесь: [link] (http://txs.io/SI5b) – dulin95

1

Вашей функции 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 как t его:

self.myUser.attemptLogin(self.passwordTextField.text, {(success: Bool, message: String) ->() in 
     if(success) { 
     //do something 
     } 
     else { 
     // do something or print message etc. 
     } 
    }) 
Смежные вопросы