AngularJSコントローラーにHTTPコードがあります:
$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 = "";
});
成功した場合、サーバーはユーザーのJSON表現で応答します。エラーの場合、サーバーはdata
パラメーターを介してアクセスできるUser not found
などの単純な文字列で応答します。
Alamofireで同じようなことをする方法を理解するのに苦労しています。私が今持っているものは次のとおりです。
@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"
});
}
}
}
エラー以外のケースを正しく処理しているかどうかもわからず、その上での入力も歓迎します。
あなたは正しい軌道に乗っていますが、現在の実装でいくつかの重要な問題に遭遇するでしょう。私はあなたを助けたいと思ういくつかの低レベルのAlamofireがあなたをつまずかせるでしょう。はるかに効果的なコードサンプルの代替バージョンを次に示します。
_@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)")
}
}
}
}
_
検証
まず、リクエストのvalidate
関数は以下を検証します:
HTTPStatusCode
-200 ... 299でなければなりませんContent-Type
_-応答のこのヘッダーは、元の要求のAccept
ヘッダーと一致する必要がありますAlamofireの検証の詳細については、 [〜#〜] readme [〜#〜] を参照してください。
弱める/強める
クロージャを弱い自己と強い自己にし、リテンションサイクルを作成しないようにします。
メインキューへのディスパッチ
メインキューへのディスパッチコールバックは必要ありません。 Alamofireは、response
およびresponseJSON
シリアライザーの完了ハンドラーがメインキューで既に呼び出されていることを保証します。実際には、必要に応じてシリアライザーを実行するための独自のディスパッチキューを提供できますが、現在のところソリューションも私のものもそうではないため、メインキューへのディスパッチ呼び出しはまったく不要です。
応答シリアライザー
特定のケースでは、responseJSON
シリアライザーを実際に使用する必要はありません。そうした場合、検証に合格しなければ、データを取り戻すことはできません。理由は、JSONシリアル化からの応答がAnyObject
として返されるものだからです。シリアル化が失敗した場合、AnyObject
はnilになり、データを読み取ることができなくなります。
代わりに、response
シリアライザーを使用し、NSJSONSerialization
を使用してデータを手動で解析してください。それが失敗した場合、適切なole NSString(data:encoding:)
メソッドに依存してデータを印刷できます。
うまくいけば、かなり複雑な方法でつまずくのを防ぐことができます。
そのため、Alamofireはすべてのリクエストを正常に処理します。これは、APIサーバーのhttpヘッダーが返されることに本当に由来します。
Alamofire.Request.validate()を使用できます
Httpヘッダーなどを検証できます。例を確認してください。
https://github.com/Alamofire/Alamofire#validation
エラーメッセージはdata
オブジェクトにあると想定しています。
データの値にアクセスするには、次のようなことができます
あなたのAPIレスポンスの外観については本当にわかりませんが、この例では
{
"message": "Could not authenticate"
}
let message: String? = data?.valueForKey("message") as String