2017-02-15 2 views
2

Недавно я переключился на Swift 3 из Swift 2 и получил ошибку с моим signInWithLogin. Я новичок и пробовал читать по этому поводу, но кажется, что с этой строкой кода ничего не изменилось, поэтому я не уверен, почему я получаю сообщение об ошибке и как его решить. Кажется, что ошибка появляется там, где находится -> in. Это что-то новое?signInWithLogin Ожидаемое выражение

import UIKit 

class LoginViewController: UIViewController, UITextFieldDelegate { 

    let invalidNetwork = "Oh Snap! You Don't Have Internet!" 

    @IBOutlet var usernameField: UITextField! 
    @IBOutlet var passwordField: UITextField! 
    @IBOutlet var loginButton: UIButton! 
    @IBOutlet var errorLabel: UILabel! 
    @IBOutlet var imageView: UIImageView! 

    var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView() 

    func displayAlert(title: String, message: String) { 

     let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert) 
     alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in 
      self.dismiss(animated: true, completion: nil) 
     })) 
     self.present(alert, animated: true, completion: nil) 

    } 

    override func viewDidLoad() { 
     tapOutKeyboard() 

     let spacerView = UIView(frame:CGRect(x:0, y:0, width:20, height:10)) 
     usernameField.leftViewMode = UITextFieldViewMode.always 
     usernameField.leftView = spacerView 

     let anotherSpacerView = UIView(frame:CGRect(x:0, y:0, width:20, height:10)) 
     passwordField.leftViewMode = UITextFieldViewMode.always 
     passwordField.leftView = anotherSpacerView 

     usernameField.delegate = self 
     passwordField.delegate = self 
    } 

    @IBAction func signupButton(_ sender: Any) { 
     _ = self.storyboard?.instantiateViewController(withIdentifier: "SignupViewController") 
     UIApplication.shared.openURL(URL(string: url.URL)!) 
    } 
    struct url { 
     static let URL = "https://www.udacity.com/account/auth#!/signup" 
    } 

    @IBAction func loginButton(_ sender: Any) { 
     dismissKeyboard() 
     self.view.endEditing(true) 

     if usernameField.text == "" || passwordField.text == "" { 

      displayAlert(title: "Oh Snap!", message: "Something Went Wrong! Try Again!") 

     } else { 

      activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) 
      activityIndicator.center = self.view.center 
      activityIndicator.hidesWhenStopped = true 
      activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray 
      view.addSubview(activityIndicator) 
      activityIndicator.startAnimating() 
      UIApplication.shared.beginIgnoringInteractionEvents() 

     } 
     let spinner = showSpinner() 
     UdacityAPI.signInWithLogin(usernameField.text!, password: passwordField.text!) { (user, error) -> in 
      spinner.hide() 
      if user != nil { 

       //Logged In! 

       self.performSegue(withIdentifier: "login", sender: self) 

       //Present The Map And Tabbed View 
       if let tabBarVC = self.storyboard?.instantiateViewController(withIdentifier: "TabBarViewController") { 
        self.present(tabBarVC, animated: true, completion: nil) 

       } 

      } else { 

       self.displayAlert(title: "Failed Logging In!", message: errorMessage) 

      } 
      if let response = user as? HTTPURLResponse { 
       if response.statusCode < 200 || response.statusCode > 300 { 
        self.displayAlert(title: "Try Again Later!", message: "Error!") 
        return 
       } 
      } 
      if let error = error { 
       //Network Error 
       if error.code == NSURLErrorNotConnectedToInternet { 

        let alertViewMessage = self.invalidNetwork 
        let okActionAlertTitle = "OK" 

        self.presentAlert("Not Online!", message: alertViewMessage, actionTitle: okActionAlertTitle, actionHandler: nil) 

       } 
      } 
     } 
    } 
} 

ответ

0

В Swift 3, затворы теперь предполагается, не маскирование, и вам необходимо, чтобы отметить закрытие, которые убегают с атрибутом @escaping. Это вызовет обработчик завершения после возвращения функции.

Вместо того чтобы использовать typealias определить обработчик завершения, вы можете альтернативно определить signInWithLogin(:) функции UdacityAPI «s как функция escaping завершения так:

static func signInWithLogin(_ username: String, password: String, completion: @escaping (_ data: Data?, _ response: URLResponse?, _ error: NSError?) -> Void) {...} 

Затем попытайтесь вызвать функцию с этим синтаксисом:

UdacityAPI.signInWithLogin(usernameField.text!, password: passwordField.text!, completion: { (user, response, error) in 
    // your code here 
}) 

Сторона примечания: см. Это сообщение для получения более подробной информации об использовании функций завершения экранирования: Swift 3 :Closure use of non-escaping parameter may allow it to escape

+0

Это было очень полезно и имело смысл! Спасибо! –

0

Да, у вас отсутствует тип возврата после ->. Глядя на ваш код, я бы сказал, что это должно быть Void, но я не могу сказать точно, поскольку у меня нет документов для вашего API.

Попробуйте добавить Void в примерно так:

UdacityAPI.signInWithLogin(usernameField.text!, password: passwordField.text!) { (user, error) -> Void in 
+0

Спасибо. Я пробовал это, и я по-прежнему получаю другую ошибку, что он не может преобразовать значение типа в ожидаемый обработчик завершения запроса типа аргумента. Я не был уверен, должен ли я добавить свой сетевой код, но вот мое репо, если это поможет лучше понять проблему: https://github.com/deborahelizabethpadilla/On-The-Map –

+0

Хорошо, еще одна вещь, которую вы могли бы попробовать: снова набрав вызов метода выше, нажмите вкладку, пока не будет выбран аргумент блока, а затем нажмите клавишу ввода. Xcode ** должен ** автоматически создавать блок с правильным синтаксисом. Затем вы можете просто скопировать код из существующего в новый, правильный. –

+0

Я пробовал это (это все тот же блок синтаксиса) и вставил (пользователь, ответ, ошибка), но теперь я получаю сообщение об ошибке в своем displayAlert прямо под ним, говоря, что «errorMessage» - это неразрешенный идентификатор и предупреждение в мой неудачный сетевой код. Я немного смущен этим, как я уже сказал, я новичок. Это нормально? Как лучше всего это исправить? –

Смежные вопросы