J'ai le code HTTP dans un contrôleur AngularJS:
$http.post('/api/users/authenticate', {email: $scope.email, password: $scope.password})
.success(function (data, status, headers, config) {
authService.login($scope.email);
$state.go('home');
})
.error(function (data, status, headers, config) {
$scope.errorMessages = data;
$scope.password = "";
});
Dans le cas de réussite, le serveur répondra avec une représentation JSON d'un utilisateur. Dans le cas d'erreur, le serveur répondra avec une chaîne simple telle que User not found
accessible par le paramètre data
.
J'ai du mal à trouver comment faire quelque chose de similaire dans Alamofire. Voici ce que j'ai en ce moment:
@IBAction func LoginPressed(sender: AnyObject) {
let params: Dictionary<String,AnyObject> = ["email": emailField.text, "password": passwordField.text]
Alamofire.request(.POST, "http://localhost:3000/api/users/authenticate", parameters: params)
.responseJSON {(request, response, data, error) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), {
let welcome = self.storyboard?.instantiateViewControllerWithIdentifier("login") as UINavigationController;
self.presentViewController(welcome, animated: true, completion: nil);
})
}
else{
dispatch_async(dispatch_get_main_queue(), {
// I want to set the error label to the simple message which I know the server will return
self.errorLabel.text = "something went wrong"
});
}
}
}
Je ne sais pas non plus si je gère correctement le cas sans erreur et j'apprécierais également une contribution à ce sujet.
Vous êtes sur la bonne voie, mais vous allez rencontrer des problèmes cruciaux avec votre implémentation actuelle. Il y a des choses Alamofire de bas niveau qui vont vous faire trébucher avec lesquelles je veux vous aider. Voici une version alternative de votre exemple de code qui sera beaucoup plus efficace.
@IBAction func loginPressed(sender: AnyObject) {
let params: [String: AnyObject] = ["email": emailField.text, "password": passwordField.text]
let request = Alamofire.request(.POST, "http://localhost:3000/api/users/authenticate", parameters: params)
request.validate()
request.response { [weak self] request, response, data, error in
if let strongSelf = self {
let data = data as? NSData
if data == nil {
println("Why didn't I get any data back?")
strongSelf.errorLabel.text = "something went wrong"
return
} else if let error = error {
let resultText = NSString(data: data!, encoding: NSUTF8StringEncoding)
println(resultText)
strongSelf.errorLabel.text = "something went wrong"
return
}
var serializationError: NSError?
if let json: AnyObject = NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments, error: &serializationError) {
println("JSON: \(json)")
let welcome = self.storyboard?.instantiateViewControllerWithIdentifier("login") as UINavigationController
self.presentViewController(welcome, animated: true, completion: nil)
} else {
println("Failed to serialize json: \(serializationError)")
}
}
}
}
Validation
Tout d'abord, la fonction validate
de la demande validera les éléments suivants:
HTTPStatusCode
- Doit être 200 ... 299Content-Type
- Cet en-tête dans la réponse doit correspondre à l'en-tête Accept
dans la demande d'origineVous pouvez trouver plus d'informations sur la validation dans Alamofire dans le readme .
Affaiblir/Fortifier
Assurez-vous de vous affaiblir et de vous affermir pour ne pas finir par créer un cycle de rétention.
Envoi vers la file d'attente principale
Vos appels de répartition vers la file d'attente principale ne sont pas nécessaires. Alamofire garantit que votre gestionnaire de complétion dans les sérialiseurs response
et responseJSON
est déjà appelé dans la file d'attente principale. Vous pouvez en fait fournir votre propre file d'attente de répartition pour exécuter les sérialiseurs si vous le souhaitez, mais ni votre solution ni la mienne ne le font actuellement, ce qui rend les appels de répartition vers la file d'attente principale complètement inutiles.
Sérialiseur de réponse
Dans votre cas particulier, vous ne voulez pas réellement utiliser le sérialiseur responseJSON
. Si vous le faites, vous ne récupérerez aucune donnée si vous ne réussissez pas la validation. La raison en est que la réponse de la sérialisation JSON est ce qui sera renvoyé comme AnyObject
. Si la sérialisation échoue, le AnyObject
sera nul et vous ne pourrez pas lire les données.
Utilisez plutôt le sérialiseur response
et essayez d'analyser les données manuellement avec NSJSONSerialization
. Si cela échoue, vous pouvez compter sur la bonne méthode ole NSString(data:encoding:)
pour imprimer les données.
J'espère que cela aidera à faire la lumière sur des moyens assez compliqués de se faire tromper.
Alamofire traite donc toutes les demandes réussies. Cela revient vraiment aux en-têtes http du serveur API renvoyés.
Vous pouvez utiliser Alamofire.Request.validate ()
Cela vous permettra de valider les en-têtes http, etc. Consultez l'exemple
https://github.com/Alamofire/Alamofire#validation
Je suppose que le message d'erreur sera dans l'objet data
.
pour accéder aux valeurs des données, vous pourriez faire quelque chose comme
Je ne suis pas vraiment sûr de votre réponse api mais dans cet exemple
{
"message": "Could not authenticate"
}
let message: String? = data?.valueForKey("message") as String