Как экранировать значение с помощью throw '() throws -> Bool' не конвертируется в 'Bool'
Я новичок в скором времени, и я был, вероятно, более часа вокруг этого.
Я делаю запрос к веб-службе, и теперь я хочу действовать в соответствии с кодом ответа (200 Ok) или другим, но я не могу понять синтаксис для возврата значения и выдачи исключения.
typealias ThrowableCallBack = () throws -> Bool
func authenticate()
{
let services = ServiceManager()
do {
try services.login(username: emailField.text!, password: passwordField.text!, authenticated: { auth in
self.loadingDialog.dismiss(animated: false, completion: {
if (auth) // '() throws -> Bool' is not convertible to 'Bool'
{
self.performSegue(withIdentifier: "LoginSegue", sender: self)
}
})
} )
}
catch RequestError.invalidRequest {
showLoginFailedAlert()
}
catch {
showLoginFailedAlert()
}
}
Потом на услуги
func login(username : String, password : String, authenticated: @escaping (_ inner: ThrowableCallBack) -> Void )
{
let parameters = [
"_username" : username,
"_password" : password
]
let request = makePostCall(request: "login", parameters: parameters, completion: {
response in
let statusCode = String(describing: response["statusCode"]!)
if (statusCode != "200")
{
authenticated( { throw RequestError.invalidRequest })
}
else
{
self.jwt = String(describing: response["jwt"]!)
authenticated( { return true })
}
} )
}
Как я должен исправить auth '() throws -> Bool' не конвертируемый в 'Bool', чтобы можно было как перехватить ошибку, так и успешно? Мой псевдоним правильный?
заранее спасибо
2 ответа
В вашем login
метод, тип параметра authenticated
является @escaping (_ inner: ThrowableCallBack) -> Void
,
Итак, закрытие перешло к authenticated
принимает один параметр типа ThrowableCallBack
, что означает параметр auth
в вашем закрытии имеет тип ThrowableCallBack
не Bool
,
Вам нужно использовать auth
как if try auth()
как ThrowableCallBack
принимает один параметр типа ()
а также throws
,
func authenticate() {
let services = ServiceManager()
services.login(username: emailField.text!, password: passwordField.text!, authenticated: { auth in
self.loadingDialog.dismiss(animated: false, completion: {
do {
if try auth() {
self.performSegue(withIdentifier: "LoginSegue", sender: self)
}
} catch RequestError.invalidRequest {
self.showLoginFailedAlert()
} catch {
self.showLoginFailedAlert()
}
})
} )
}
Чтобы это работало, вам может потребоваться изменить тип authenticated
следующее:
func login(username : String, password : String,
authenticated: @escaping (_ inner: @escaping ThrowableCallBack) -> Void ) {
//...
}
В любом случае, тип замыкания, принимающий параметр другого типа замыкания, очень запутан, и вам лучше пересмотреть свой дизайн.
(Сложение)
Когда вы получаете ошибки во время выполнения, говорящие о некоторых вещах основного потока, вам может потребоваться использовать DispatchQueue.main
как найдено во многих асинхронных примерах:
func authenticate() {
let services = ServiceManager()
services.login(username: emailField.text!, password: passwordField.text!, authenticated: { auth in
DispatchQueue.main.async {
self.loadingDialog.dismiss(animated: false, completion: {
do {
if try auth() {
self.performSegue(withIdentifier: "LoginSegue", sender: self)
}
} catch RequestError.invalidRequest {
self.showLoginFailedAlert()
} catch {
self.showLoginFailedAlert()
}
})
}
} )
}
Вы можете взглянуть на эту тему
Мы используем Completion
перечислить, чтобы сделать это
public enum Completion<E:Error> {
case success
case failure(E)
}
Реализуйте это в вашей функции следующим образом:
func login(username : String, password : String, authenticated: @escaping (Completion<ServiceError> )
{
...
if (statusCode != "200") {
authenticated(.failure(ServiceError.accessDenied))
} else {
self.jwt = String(describing: response["jwt"]!)
authenticated(.success)
}
...
}
Проверьте это следующим образом:
try services.login(username: emailField.text!, password: passwordField.text!, authenticated: { auth in
switch auth {
case .success: //handle success
case .failure(let error): print(error)
}
}
Заметка ServiceError
это перечисление, которое реализует Error и содержит все различные виды сервисных ошибок, которые мы потенциально можем получить.
Мы используем аналогичное перечисление в случае, когда мы хотим вернуть результат.
public enum Result<Value, E:Error> {
case success(Value)
case failure(E)
}