I want to add 2 parameters to NSURLRequest
.
Is there a way or should I use AFnetworking?
Asked
Active
Viewed 2.1k times
11
2 Answers
35
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]; }

Rob
- 415,655
- 72
- 787
- 1,044
-
yes i am receiving JSON .this is great and complete answer.THAKS man! :) Can i ask you just one thing for AFNetworking. this is my code :[manager POST:@"tourneys/portal.php" parameters:@{ @"cmd":@"get_games", @"uid_first":@"1" } success:^(NSURLSessionDataTask *task, id responseObject) { NSDictionary* response = (NSDictionary* )responseObject; I am receiving json from my server. Is this cast to NSDictionary valid .I saw it's working but i can't figure it out why.I am not using explicit any serialiser. Thanks in advance. – l.vasilev Sep 07 '14 at 13:43
-
1Since you haven't specified a `responseSerializer`, that means you're using the default `AFJSONResponseSerializer`. So, it's doing the JSON conversion for you. – Rob Sep 07 '14 at 14:37
-
For iOS 9 replace `CFURLCreateStringByAddingPercentEscapes()` by `stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]` in `percentEscapeString:`. – AppsolutEinfach May 23 '16 at 13:41
-
1@AppsolutEinfach - No, because that character set will let `&` and `+` pass unescaped (because they're allowed in query URL; but if these delimiters occur within value within query, you have to escape them). See part 2 of http://stackoverflow.com/a/35912606/1271826 if you want to see how you have to modify `URLQueryAllowedCharacterSet` properly. – Rob May 23 '16 at 15:35
-
@Rob - You're totally right. Thanks for your correction. – AppsolutEinfach Jun 07 '16 at 05:39
-
I would argue that attaching libraries is the best way of doing everything. AFNetworking is not required at this point. No need to attach extra dependency. – Nat Dec 20 '18 at 11:50
-
To each his own. That’s why I outlined both approaches above. – Rob Dec 20 '18 at 14:45
1
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

eosterberg
- 1,422
- 11
- 11
-
5`URLWithString`requires a properly encoded URL. Your approach does not encode the URL components at all. So, it will fail eventually. – CouchDeveloper Sep 06 '14 at 15:50
-
It won't "fail eventually". It will fail if some special char is in the parameter – Doon Jan 02 '20 at 22:25