Alamofire中的错误处理

Pay*_*ian 15 ios angularjs swift alamofire

我在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 = "";
    });
Run Code Online (Sandbox Code Playgroud)

在成功的情况下,服务器将使用用户的JSON表示进行响应.在错误情况下,服务器将使用简单的字符串进行响应,例如User not found可以通过data参数访问.

我无法弄清楚如何在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"
                });
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道我是否正确处理了非错误情况,并且也希望对此进行输入.

cno*_*oon 28

您处于正确的轨道上,但是您将遇到当前实施的一些关键问题.有一些低级别的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)")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

验证

首先,validate请求上的函数将验证以下内容:

  • HTTPStatusCode - 必须是200 ... 299
  • Content-Type- 响应中的此标头必须与Accept原始请求中的标头匹配

您可以在README中找到有关Alamofire中验证的更多信息.

弱化/强化

确保你的关闭弱自我和强自我,以确保你不会最终创建一个保留周期.

派遣到主队列

您的调度回调到主队列是没有必要的.Alamofire保证在你完成处理responseresponseJSON串行被称为主队列了.如果您愿意,您实际上可以提供自己的调度队列来运行序列化程序,但是您的解决方案或我的解决方案当前都没有这样做,因此完全不需要对主队列的调度调用.

响应序列化器

在您的特定情况下,您实际上并不想使用responseJSON序列化程序.如果您这样做,如果您未通过验证,则不会最终获得任何数据.原因是来自JSON序列化的响应将作为返回的内容返回AnyObject.如果序列化失败,则AnyObject为零,您将无法读取数据.

而是使用response序列化程序并尝试手动解析数据NSJSONSerialization.如果失败了,那么你可以依靠good ole NSString(data:encoding:)方法打印出数据.

希望这有助于揭示一些相当复杂的方法来绊倒.

  • 很好的问题,不可能给出一个简明的答案.这取决于您想要的行为.如果你希望`loginPressed`方法的所有者被保存在内存中,不管其他什么都没有引用它,那么你就不想使用`[weak self]`.但是,如果不使用弱化/强化模式,则始终存在创建保留周期的潜在风险.更多信息[这里](http://blackpixel.com/blog/2014/03/capturing-myself.html)和[here](http://stackoverflow.com/questions/24320347/shall-we-always-use -unowned自内闭合功能于SWIFT). (4认同)