So Im new in programming with Objective-c. I want to make request with HTTP POST Method.The parameter that i'm sending is of type int.
I'm getting this error :
[__NSCFNumber stringByAddingPercentEncodingWithAllowedCharacters:]: unrecognized selector sent to instance 0xb0000000000048d3
at this line of code :
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowed];
The whole Code:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
request.HTTPMethod = #"POST";
[request setHTTPBody:[self httpBodyForParameters:params]];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"dataTaskWithRequest error: %#", error);
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(#"Expected responseCode == 200; received %ld", (long)statusCode);
}}
NSError *parseError;
id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (!responseObject) {
NSLog(#"JSON parse error: %#", parseError);
} else {
NSLog(#"responseObject = %#", responseObject);
}
NSLog(#"print123");
}];
[task resume];
}
- (NSData *)httpBodyForParameters:(NSDictionary *)parameters {
NSMutableArray *parameterArray = [NSMutableArray array];
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
NSString *param = [NSString stringWithFormat:#"%#=%#", [self percentEscapeString:key], [self percentEscapeString:obj]];
[parameterArray addObject:param];
}];
NSString *string = [parameterArray componentsJoinedByString:#"&"];
return [string dataUsingEncoding:NSUTF8StringEncoding];
}
- (NSString *)percentEscapeString:(NSString *)string {
NSCharacterSet *allowed = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"];
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowed];
}
#Paulw11 is right that the error is the result of a number being treated as a string. An immediate (but a little clunky) fix is to be less committed to the type of values you find when enumerating the dictionary...
// notice we change the type of obj id, not NSString*
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
// now, test for it's type and treat accordingly
NSString *objString = ([obj isKindOfClass:[NSString self]])? [self percentEscapeString:obj] : [obj stringValue];
NSString *param = [NSString stringWithFormat:#"%#=%#", [self percentEscapeString:key], objString];
[parameterArray addObject:param];
}];
But this brittle solution now works only for strings and numbers. If you can convince the server to accept JSON, then the request code can be simplified and generalized like this...
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
request.HTTPMethod = #"POST";
// params is your original (serializable) dictionary
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject: params options:0 error:&error];
[request setHTTPBody:postData];
NSURLSessionTask *task = // ...
Related
In my project i am passing this API: http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat with params: prod_id=25,var_id=140.
The problem is when i am pass this api in Rest Client it displays correct response but when i am trying to put it in my code it shows different response.
i am using the following code:
-(void)listofNotice
{
NSString *post = [NSString stringWithFormat:#"prod_id=25,var_id=140"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
//NSString *str=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
//NSLog(#"str : %#",str);
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
}
- (id)cleanJsonToObject:(id)data
{
NSError* error;
if (data == (id)[NSNull null])
{
return [[NSObject alloc] init];
}
id jsonObject;
if ([data isKindOfClass:[NSData class]])
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
}
else
{
jsonObject = data;
}
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSMutableArray *array = [jsonObject mutableCopy];
for (int i = (int)array.count-1; i >= 0; i--)
{
id a = array[i];
if (a == (id)[NSNull null])
{
[array removeObjectAtIndex:i];
} else
{
array[i] = [self cleanJsonToObject:a];
}
}
return array;
}
else if ([jsonObject isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictionary = [jsonObject mutableCopy];
for(NSString *key in [dictionary allKeys])
{
id d = dictionary[key];
if (d == (id)[NSNull null])
{
dictionary[key] = #"";
} else
{
dictionary[key] = [self cleanJsonToObject:d];
}
}
return dictionary;
}
else
{
return jsonObject;
}
}
it display the following response:
str : {
business = 0;
"business-list" = "Business list empty.";
response = 401;
}
but the actual response is something like this
please help me.. Thanks In advance
Please change this
NSString *post = [NSString stringWithFormat:#"prod_id=25,var_id=140"];
To:
NSString * post =[NSString stringWithFormat:#"prod_id=25&var_id=140"];
if possible use this:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.HTTPAdditionalHeaders = #{#"application/x-www-form-urlencoded" : #"Content-Type"};
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:#"http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *requestData = [post dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:requestData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data != nil){
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger code = [httpResponse statusCode];
NSLog(#"Status Code: %ld", (long)code);
if (code == 200) {
NSError *error;
id responseObject =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
}
}
}];
[postDataTask resume];
OR
NSString *postString = [NSString stringWithFormat:#"prod_id=%#&var_id=%#",#"25",#"140"];
NSURL *urlPath = [NSURL URLWithString:#"http://dev-demo.info.bh-in-15.webhostbox.net/dv/nationalblack/api/businessbysubcat"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlPath
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
NSData *requestData = [postString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:requestData];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[APP_DELEGATE removeLoader];
if(data != nil) {
NSDictionary *responseObject =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSLog(#" %#", responseObject);
}
else {
}
}];
Hope this helps.
I think you need to change below code
NSString *post = [NSString stringWithFormat:#"prod_id=25,var_id=140"];
to
NSDictionary *prodDict=#{#"prod_id":#"25",
#"var_id":#"140"};
I have a NSString which contains the URL. I want to make a GET request using the URL and also check if the response is 200.
With the current code i get response as 0.
Here is my code:
NSString *Url = #"http://www.xyx.com";
NSData *data = [Url dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *len = [NSString stringWithFormat:#"%lu", (unsigned long)[data length]];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc]init];
[req setURL:[NSURL URLWithString:Url]];
[req setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:req completionHandler:^(NSData data, NSURLResponse response, NSError *error) {
NSString *req = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"Reply = %#", req);
}]resume];
use this code it works for you:
-(void)yourMethodNAme
{
NSString *post = #"";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"Your URL"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
//NSString *str=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
//NSLog(#"str : %#",str);
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
//NSLog(#"str : %#",dict6);
}
- (id)cleanJsonToObject:(id)data
{
NSError* error;
if (data == (id)[NSNull null])
{
return [[NSObject alloc] init];
}
id jsonObject;
if ([data isKindOfClass:[NSData class]])
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
}
else
{
jsonObject = data;
}
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSMutableArray *array = [jsonObject mutableCopy];
for (int i = (int)array.count-1; i >= 0; i--)
{
id a = array[i];
if (a == (id)[NSNull null])
{
[array removeObjectAtIndex:i];
} else
{
array[i] = [self cleanJsonToObject:a];
}
}
return array;
}
else if ([jsonObject isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictionary = [jsonObject mutableCopy];
for(NSString *key in [dictionary allKeys])
{
id d = dictionary[key];
if (d == (id)[NSNull null])
{
dictionary[key] = #"";
} else
{
dictionary[key] = [self cleanJsonToObject:d];
}
}
return dictionary;
}
else
{
return jsonObject;
}
}
and finally call it in ViewDidLoad as [self yourMethodNAme];
-(void) httpGetWithCustomDelegateWithString: (NSString*)urlString
{
[self startActivity];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *dataTask =[defaultSession dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSLog(#"Response:%# %#\n", response, error);
if(error == nil)
{
//NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
//NSLog(#"Data = %#",text);
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
deserializedDictionary = nil;
if (jsonObject != nil && error == nil)
{
if ([jsonObject isKindOfClass:[NSDictionary class]])
{
//Convert the NSData to NSDictionary in this final step
deserializedDictionary = (NSDictionary *)jsonObject;
NSLog(#"dictionary : %#",deserializedDictionary);
}
if ([jsonObject isKindOfClass:[NSArray class]])
{
deserializedArr = (NSArray*)jsonObject;
NSLog(#"array : %#",deserializedArr);
}
}
[self setAlert];
}
else
{
[activityView removeFromSuperview];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
[self showAlert:#"Error" :#"Network error occured." :#"Ok"];
}
}];
[dataTask resume];
}
just use the above code and call it by
[self httpGetWithCustomDelegateWithString:#"webStringHere"];
On Completion, it will call the method -(void)setAlert; so declare it in your class where you use this.
This may be due to App Transport Security blocking HTTP.
App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.
Try making a request to a secure site (e.g. https://www.google.com) as a test.
I want to add 2 parameters to NSURLRequest.
Is there a way or should I use AFnetworking?
It will probably be easier to do if you use AFNetworking. If you have some desire to do it yourself, you can use NSURLSession, but you have to write more code.
If you use AFNetworking, it takes care of all of this gory details of serializing the request, differentiating between success and errors, etc.:
NSDictionary *params = #{#"firstname": #"John", #"lastname": #"Doe"};
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:urlString parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"responseObject = %#", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"error = %#", error);
}];
This assumes that the response from the server is JSON. If not (e.g. if plain text or HTML), you might precede the POST with:
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
If doing it yourself with NSURLSession, you might construct the request like so:
NSDictionary *params = #{#"firstname": #"John", #"lastname": #"Doe"};
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[self httpBodyForParameters:params]];
You now can initiate the request with NSURLSession. For example, you might do:
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"dataTaskWithRequest error: %#", error);
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(#"Expected responseCode == 200; received %ld", (long)statusCode);
}
}
// If response was JSON (hopefully you designed web service that returns JSON!),
// you might parse it like so:
//
// NSError *parseError;
// id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
// if (!responseObject) {
// NSLog(#"JSON parse error: %#", parseError);
// } else {
// NSLog(#"responseObject = %#", responseObject);
// }
// if response was text/html, you might convert it to a string like so:
//
// NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// NSLog(#"responseString = %#", responseString);
}];
[task resume];
Where
/** Build the body of a `application/x-www-form-urlencoded` request from a dictionary of keys and string values
#param parameters The dictionary of parameters.
#return The `application/x-www-form-urlencoded` body of the form `key1=value1&key2=value2`
*/
- (NSData *)httpBodyForParameters:(NSDictionary *)parameters {
NSMutableArray *parameterArray = [NSMutableArray array];
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
NSString *param = [NSString stringWithFormat:#"%#=%#", [self percentEscapeString:key], [self percentEscapeString:obj]];
[parameterArray addObject:param];
}];
NSString *string = [parameterArray componentsJoinedByString:#"&"];
return [string dataUsingEncoding:NSUTF8StringEncoding];
}
and
/** Percent escapes values to be added to a URL query as specified in RFC 3986.
See http://www.ietf.org/rfc/rfc3986.txt
#param string The string to be escaped.
#return The escaped string.
*/
- (NSString *)percentEscapeString:(NSString *)string {
NSCharacterSet *allowed = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"];
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowed];
}
NSDictionary *params = #{#"firstname": #"John", #"lastname": #"Doe"};
NSMutableString *str = [NSMutableString stringWithString:#"http://yoururl.com/postname?"];
NSArray *keys = [params allKeys];
NSInteger counter = 0;
for (NSString *key in keys) {
[str appendString:key];
[str appendString:#"="];
[str appendString:params[key]];
if (++counter < keys.count) { // more params to come...
[str appendString:#"&"];
}
}
NSURL *url = [NSURL URLWithString:str];
// should give you: http://yoururl.com/postname?firstname=John&lastname=Doe
// not tested, though
Hi i am very new for ios and in my project i am using NSUrlSession for calling services
but in my below code i have maintain if and else conditions for handing server response but those if and else conditions not calling
please help me where was the mistack happand?
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:myurl here]];
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"GET"];
[request setHTTPBody:[self httpBodyForParamsDictionary:params]];
//You now can initiate the request with NSURLSession or NSURLConnection, however you prefer. For example, with NSURLSession, you might do:
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"dataTaskWithRequest error: %#", error);
NSString * BasicnetworkError = [error localizedDescription];
NSString * AppendString = #"Http Response failed with the following ";
NSString * networkError = [AppendString stringByAppendingString:BasicnetworkError];
[self BasicError1:networkError];
}
else if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(#"Expected responseCode == 200; received %ld", (long)statusCode);
NSString *statusCodeError = [NSString stringWithFormat: #"Http Response failed with the following code %ld", (long)statusCode];
[self BasicError1:statusCodeError];
}
}
// If response was JSON (hopefully you designed web service that returns JSON!),
// you might parse it like so:
else{
NSError *parseError;
id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(#"else condtion");
if (!responseObject) {
NSLog(#"JSON parse error: %#", parseError);
} else {
NSLog(#"responseObject = %#", responseObject);
[self MainService:responseObject];
}
//if response was text/html, you might convert it to a string like so:
// ---------------------------------
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"final responseString = %#", responseString);
}
}];
[task resume];
}
- (NSData *)httpBodyForParamsDictionary:(NSDictionary *)paramDictionary{
NSMutableArray *parameterArray = [NSMutableArray array];
[paramDictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
NSString *param = [NSString stringWithFormat:#"%#=%#", key, [self percentEscapeString:obj]];
[parameterArray addObject:param];
}];
NSString *string = [parameterArray componentsJoinedByString:#"&"];
return [string dataUsingEncoding:NSUTF8StringEncoding];
}
- (NSString *)percentEscapeString:(NSString *)string{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)#" ",
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
There was a case of wrong if else block mentioned in your code. please use below code.
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *mainDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"COLLECTION",#"SearchBy",
#"1284",#"SearchKey",
#"",#"Color",
#"",#"PriceFrom",
#"",#"PriceTo",
#"",#"QtyFrom",
#"",#"QtyTo",
nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://203.77.214.78/StockManager/SL/SearchProducts"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[self httpBodyForParamsDictionary:mainDictionary]];
//You now can initiate the request with NSURLSession or NSURLConnection, however you prefer. For example, with NSURLSession, you might do:
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"dataTaskWithRequest error: %#", error);
}
else if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(#"Expected responseCode == 200; received %ld", (long)statusCode);
}else{
NSError *parseError;
id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(#"else condtion");
if (!responseObject) {
NSLog(#"JSON parse error: %#", parseError);
} else {
NSLog(#"responseObject = %#", responseObject);
}
//if response was text/html, you might convert it to a string like so:
// ---------------------------------
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"final responseString = %#", responseString);
}
}
}];
[task resume];
}
I want to add 2 parameters to NSURLRequest.
Is there a way or should I use AFnetworking?
It will probably be easier to do if you use AFNetworking. If you have some desire to do it yourself, you can use NSURLSession, but you have to write more code.
If you use AFNetworking, it takes care of all of this gory details of serializing the request, differentiating between success and errors, etc.:
NSDictionary *params = #{#"firstname": #"John", #"lastname": #"Doe"};
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:urlString parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"responseObject = %#", responseObject);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"error = %#", error);
}];
This assumes that the response from the server is JSON. If not (e.g. if plain text or HTML), you might precede the POST with:
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
If doing it yourself with NSURLSession, you might construct the request like so:
NSDictionary *params = #{#"firstname": #"John", #"lastname": #"Doe"};
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[self httpBodyForParameters:params]];
You now can initiate the request with NSURLSession. For example, you might do:
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"dataTaskWithRequest error: %#", error);
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(#"Expected responseCode == 200; received %ld", (long)statusCode);
}
}
// If response was JSON (hopefully you designed web service that returns JSON!),
// you might parse it like so:
//
// NSError *parseError;
// id responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
// if (!responseObject) {
// NSLog(#"JSON parse error: %#", parseError);
// } else {
// NSLog(#"responseObject = %#", responseObject);
// }
// if response was text/html, you might convert it to a string like so:
//
// NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// NSLog(#"responseString = %#", responseString);
}];
[task resume];
Where
/** Build the body of a `application/x-www-form-urlencoded` request from a dictionary of keys and string values
#param parameters The dictionary of parameters.
#return The `application/x-www-form-urlencoded` body of the form `key1=value1&key2=value2`
*/
- (NSData *)httpBodyForParameters:(NSDictionary *)parameters {
NSMutableArray *parameterArray = [NSMutableArray array];
[parameters enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) {
NSString *param = [NSString stringWithFormat:#"%#=%#", [self percentEscapeString:key], [self percentEscapeString:obj]];
[parameterArray addObject:param];
}];
NSString *string = [parameterArray componentsJoinedByString:#"&"];
return [string dataUsingEncoding:NSUTF8StringEncoding];
}
and
/** Percent escapes values to be added to a URL query as specified in RFC 3986.
See http://www.ietf.org/rfc/rfc3986.txt
#param string The string to be escaped.
#return The escaped string.
*/
- (NSString *)percentEscapeString:(NSString *)string {
NSCharacterSet *allowed = [NSCharacterSet characterSetWithCharactersInString:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"];
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowed];
}
NSDictionary *params = #{#"firstname": #"John", #"lastname": #"Doe"};
NSMutableString *str = [NSMutableString stringWithString:#"http://yoururl.com/postname?"];
NSArray *keys = [params allKeys];
NSInteger counter = 0;
for (NSString *key in keys) {
[str appendString:key];
[str appendString:#"="];
[str appendString:params[key]];
if (++counter < keys.count) { // more params to come...
[str appendString:#"&"];
}
}
NSURL *url = [NSURL URLWithString:str];
// should give you: http://yoururl.com/postname?firstname=John&lastname=Doe
// not tested, though