AFNetworking - How to make POST request

EDIT 07/14

As Bill Burgess mentionned in a comment of his answer, this question is related to the version 1.3 of AFNetworking. It may be outdated for the newcomers here.


I'm quite new to iPhone development, and I'm using AFNetworking as my services library.

The API i'm querying is a RESTful one, and I need to make POST requests. To do this, I tried with the following code :

NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:@"my_username", @"username", @"my_password", @"password", nil];
NSURL *url = [NSURL URLWithString:@"http://localhost:8080/login"];

NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
    NSLog(@"Pass Response = %@", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
    NSLog(@"Failed Response : %@", JSON);
}];
[operation start];

There are two main issues with this code :

  • AFJSONRequestOperation seems to make a GET request, not a POST one.
  • I can't put parameters to this method.

I also tried with this code :

NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:@"my_username", @"username", @"my_password", @"password", nil];
NSURL *url = [NSURL URLWithString:@"http://localhost:8080"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];

[httpClient postPath:@"/login" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"Succes : %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Failure : %@", error);
}];

Is there a better way to make what I want here to get it done ?

Thanks for the help !

Answers


You can override the default behavior of your request being used with AFNetworking to process as a POST.

NSURLRequest *request = [client requestWithMethod:@"POST" path:path parameters:nil];

This assumes you have overridden the default AFNetworking setup to use a custom client. If you aren't, I would suggest doing it. Just create a custom class to handle your network client for you.

MyAPIClient.h

#import <Foundation/Foundation.h>
#import "AFHTTPClient.h"

@interface MyAPIClient : AFHTTPClient

+(MyAPIClient *)sharedClient;

@end

MyAPIClient.m

@implementation MyAPIClient

+(MyAPIClient *)sharedClient {
    static MyAPIClient *_sharedClient = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:webAddress]];
    });
    return _sharedClient;
}

-(id)initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (!self) {
        return nil;
    }
    [self registerHTTPOperationClass:[AFJSONRequestOperation class]];
    [self setDefaultHeader:@"Accept" value:@"application/json"];
    self.parameterEncoding = AFJSONParameterEncoding;

    return self;

}

Then you should be able to fire off your network calls on the operation queue with no problem.

    MyAPIClient *client = [MyAPIClient sharedClient];
    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
    [[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount];

    NSString *path = [NSString stringWithFormat:@"myapipath/?value=%@", value];
    NSURLRequest *request = [client requestWithMethod:@"POST" path:path parameters:nil];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
        // code for successful return goes here
        [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];

        // do something with return data
    }failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
        // code for failed request goes here
        [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount];

        // do something on failure
    }];

    [operation start];

Need Your Help

Adding a colored background with text/icon under swiped row when using Android's RecyclerView

android android-layout android-canvas android-support-library android-recyclerview

EDIT: The real problem was that my LinearLayout was wrapped in another layout, which caused the incorrect behavior. The accepted answer by Sanvywell has a better, more complete example of how to dr...

Get parent class name from child with ES6?

javascript ecmascript-6

I would like to get the parent class name (Parent), but I'm only able to retrieve the child class name with this code (Child)...