Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alamofire POST request with Swift 2

I am trying to make a POST request in Alamofire to return a JSON object. This code worked in Swift 1, but in swift 2 I get this invalid parameter issue:

Tuple types '(NSURLRequest?, NSHTTPURLResponse?, Result<AnyObject>)' (aka '(Optional<NSURLRequest>, Optional<NSHTTPURLResponse>, Result<AnyObject>)') and '(_, _, _, _)' have a different number of elements (3 vs. 4)

It seems like the error parameter was removed, but I am using the error parameter inside the function to check for errors, so how would I do that without an error param?

Here's my code for the POST request:

            let response = Alamofire.request(.POST, urlPath, parameters: parameters, encoding: .URL)
            .responseJSON { (request, response, data, error) in
                if let anError = error
                {
                    // got an error in getting the data, need to handle it
                    print("error calling POST on /posts")
                    print(error)
                }
                else if let data: AnyObject = data
                {
                    // handle the results as JSON, without a bunch of nested if loops
                    let post = JSON(data)
                    // to make sure it posted, print the results
                    print("The post is: " + post.description)
                }
        }
like image 234
mattgabor Avatar asked Aug 28 '15 18:08

mattgabor


2 Answers

If you see the documentation in the branch Swift2.0 you can see that the responseJSON function has changed as the error says, it have now three parameters but you can catch the error too, lets take a look:

public func responseJSON(
    options options: NSJSONReadingOptions = .AllowFragments,
    completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<AnyObject>) -> Void)
    -> Self
{
    return response(
        responseSerializer: Request.JSONResponseSerializer(options: options),
        completionHandler: completionHandler
    )
}

Now it returns an enum Result<AnyObject> and according to the doc :

Used to represent whether a request was successful or encountered an error.

- Success: The request and all post processing operations were successful resulting in the serialization of the 
           provided associated value.
- Failure: The request encountered an error resulting in a failure. The associated values are the original data 
           provided by the server as well as the error that caused the failure.

And it have inside an property entitled error, with the following doc:

/// Returns the associated error value if the result is a failure, `nil` otherwise.
public var error: ErrorType? {
    switch self {
    case .Success:
        return nil
    case .Failure(_, let error):
        return error
    }
}

Then if you follow this test case inside Alamofire you can see how to get the error properly:

func testThatResponseJSONReturnsSuccessResultWithValidJSON() {
    // Given
    let URLString = "https://httpbin.org/get"
    let expectation = expectationWithDescription("request should succeed")

    var request: NSURLRequest?
    var response: NSHTTPURLResponse?
    var result: Result<AnyObject>!

    // When
    Alamofire.request(.GET, URLString, parameters: ["foo": "bar"])
        .responseJSON { responseRequest, responseResponse, responseResult in
            request = responseRequest
            response = responseResponse
            result = responseResult

            expectation.fulfill()
        }

    waitForExpectationsWithTimeout(defaultTimeout, handler: nil)

    // Then
    XCTAssertNotNil(request, "request should not be nil")
    XCTAssertNotNil(response, "response should not be nil")
    XCTAssertTrue(result.isSuccess, "result should be success")
    XCTAssertNotNil(result.value, "result value should not be nil")
    XCTAssertNil(result.data, "result data should be nil")
    XCTAssertTrue(result.error == nil, "result error should be nil")
}

UPDATE:

Alamofire 3.0.0 introduces a Response struct. All response serializers (with the exception of response) return a generic Response struct.

public struct Response<Value, Error: ErrorType> {
   /// The URL request sent to the server.
   public let request: NSURLRequest?

   /// The server's response to the URL request.
   public let response: NSHTTPURLResponse?

   /// The data returned by the server.
   public let data: NSData?

   /// The result of response serialization.
   public let result: Result<Value, Error>
}

So you can call it like the following way:

Alamofire.request(.GET, "http://httpbin.org/get")
     .responseJSON { response in
         debugPrint(response)
}

You can read more about the migration process in the Alamofire 3.0 Migration Guide.

I hope this help you.

like image 186
Victor Sigler Avatar answered Oct 26 '22 15:10

Victor Sigler


Have you tried using three parameters in the .responseJSON and inserting a try catch block around the areas you want error logging, check out this link if you need help with swift 2 try catchs

like image 40
Vladmrnv Avatar answered Oct 26 '22 15:10

Vladmrnv