Ваша операция async, способ ожидания завершения заключается в том, что вы используете закрытие, вы пытаетесь вернуть значение за пределы закрытия, так что значение еще не получено! и это причина вашего пустого значения, вы можете «выбросить» на completionHandler
внутри закрытия, как в следующем примере:
func alamoRequest(username : String, email: String, password: String, facebook: String, completionHandler : (String?) -> Void) {
var jsonValue : JSON?
let URL = "http://someurl.com/login.php"
let requestParameters = ["username" : username, "email" : email, "password" : password, "facebook" : facebook, "date": NSNull()];
var jsonString : String = String()
Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON {
response in
switch response.result {
case .Success:
if let value = response.result.value {
jsonValue = JSON(value)
jsonString = jsonValue!["error"].stringValue
print("Value in implementation is: \(jsonString)")
completionHandler(jsonString)
}
case .Failure(let error):
print(error)
}
}
}
Тем не менее, в приведенном выше способом единственный способ вас не знаю, существуют ли некоторые ошибка в запросе, потому что ваш completionHandler
вызывается только в корпусе .Success
, если вы хотите, вы можете называть его всегда, после последнего case
enum
.
Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON {
response in
switch response.result {
case .Success:
if let value = response.result.value {
jsonValue = JSON(value)
jsonString = jsonValue!["error"].stringValue
print("Value in implementation is: \(jsonString)")
}
case .Failure(let error):
jsonString = nil
}
completionHandler(jsonString)
}
}
И если jsonString
это nil
имеет ocurred некоторых ошибок, но опять же вы ничего об ошибке не знаете, то у вас есть два варианта:
- Поменяйте ваше замыкание всегда возвращать
jsonString
и error
- Инкапсулирование ошибки в бросающееся закрытие.
Первый случай очень прост, просто измените свое закрытие и всегда возвращайте ошибку, если это nil
, тогда никаких ошибок не возникло.
Другой вариант Я думаю, что это лучше, как в следующем примере:
func alamoRequest(username : String, email: String, password: String, facebook: String,
completion: (inner:() throws -> String) ->()) {
var jsonValue : JSON?
let URL = "http://someurl.com/login.php"
let requestParameters = ["username" : username, "email" : email, "password" : password, "facebook" : facebook, "date": NSNull()];
var jsonString : String = String()
Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON {
response in
switch response.result {
case .Success:
if let value = response.result.value {
jsonValue = JSON(value)
jsonString = jsonValue!["error"].stringValue
print("Value in implementation is: \(jsonString)")
completionHandler(inner: { return jsonString })
}
case .Failure(let error):
completionHandler(inner: { return error })
}
}
}
И тогда вы можете назвать это как следующим образом:
self.alamoRequest(usernameField.text!, email: emailField.text!, password: passwordField.text!, facebook: "false") { (inner:() throws -> String) -> Void in
do {
let result = try inner()
} catch let error {
print(error)
}
}
Хитрость заключается в том, что alamoRequest
функция занимает дополнительное закрытие под названием 'inner'
типа () throws -> String
. Это закрытие либо даст результат вычисления, либо оно будет выдано.Сама крышка строится в процессе вычисления одним из двух способов:
- В случае ошибки:
inner: {throw error}
- В случае успеха:
inner: {return result}
Я настоятельно рекомендую вам отличную статью об использовании try/catch
in async calls Using try/catch in Swift with asynchronous closures
Надеюсь, это поможет вам.
Большое спасибо Виктору, очень подробный и проницательный ответ, это действительно помогло мне! :-) –