NSURLSessionDataTask returning incorrect result - ios

I have used following code for Posting request through NSURLSession, but it is returning incorrect result. but if I check it with POSTMAN with same parameters and url then it's working fine. Please help.
// URL of the endpoint we're going to contact.
NSURL *url = url;
// Create a simple dictionary with numbers.
NSDictionary *param = #{#"key1": #"value1"};
NSError *error = nil;
// Convert the dictionary into JSON data.
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:param
options:kNilOptions error:&error];
// Create a POST request with our JSON as a request body.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = #"POST";
request.HTTPBody = JSONData;
// Create a task.
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error)
{
if (!error)
{
if (data) {
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
success(json);
}
else {
failure(error);
NSLog(#"******************* error in sendRequestToServer");
}
//NSLog(#"Status code: %i", ((NSHTTPURLResponse *)response).statusCode);
}
else {
failure(error);
NSLog(#"******************* error in sendRequestToServer");
}
}];
// Start the task.
[task resume];

I'd start by setting the Content-Type header. Most servers handle POST requests differently depending on the content type, and you aren't setting one.

Related

Converting URL into NSDATA and Parsing The JSON is right way or not?

NSData *weatherData = [[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"our URL"]];
NSMutableDictionary *weatherDict = [NSJSONSerialization JSONObjectWithData:weatherData options:kNilOptions error:&error];
Getiing JSON Data with NSDATA is right way or not?
For parser JSON better options use:
1) NSURLSession.
2) AFNetworking .
Using above approve you can handle response and error (If the request failed or encountered an error )
For NSURLSession :
-(void)getJsonResponseFromServer : (NSString *)urlString parameter :(NSDictionary*)parameter success : (void (^)(NSDictionary *responseDict))success failure:(void(^)(NSError* error))failure
{
NSError* error=nil;
NSURLSession * session = [NSURLSession sharedSession];
NSURL * url = [NSURL URLWithString: urlString];
NSData *postData = [NSJSONSerialization dataWithJSONObject:parameter options:0 error:&error];
//Create URLReques
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
// [request addValue:#"application/json" forHTTPHeaderField:#"Accept"];
// Set Method POST/GET
[request setHTTPMethod:#"POST"];
//set Parameter
[request setHTTPBody:postData];
// Asynchronously Api is hit here
NSURLSessionDataTask* dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) //If error nil
{
//Serialization data
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"json %#",json);
success(json);
}
else
{
failure(error);
}
}];
[dataTask resume] ; // Executed task
}
Simply call :
NSDictionary* paramDict=#{#“paramterName”:#“value”};
[self getJsonResponseFromServer:#BaseURL parameter:paramDict success:^(NSDictionary *responseDict)
{
NSLog(#"responce %#",responseDict);
} failure:^(NSError *error)
{
// error handling here ...
NSLog(#"error %#",error.description);
}];
for better understanding NSURLSession Class Reference refer :

Getting data back from an NSURLSession via POST with JSON

Since NSURLConnection is depreated I need to move to an NSURLSession. I have a URL and some data I need to input as JSON. Then the result should be JSON coming back. I see something like so:
NSError *error;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:#"[JSON SERVER"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPMethod:#"POST"];
NSDictionary *mapData = [[NSDictionary alloc] initWithObjectsAndKeys: #"TEST IOS", #"name",
#"IOS TYPE", #"typemap",
nil];
NSData *postData = [NSJSONSerialization dataWithJSONObject:mapData options:0 error:&error];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
[postDataTask resume];
I this the correct approach?
My requirements are:
1. Turn my key value pairs into JSON.
2. Pass in the URL and JSON to a reusable function.
3. Get the JSON data returned.
4. Parse the JSON data returned.
Have the callers to your method to provide a completion handler which processes the data returned and update the UI to indicate completion.
You can copy the pattern found in the SDK, as follows:
- (void)makeRequest:(NSString *)param completion:(void (^)(NSDictionary *, NSError *))completion;
Implement it like this:
// in the same scope
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
- (void)makeRequest:(NSString *)param
completion:(void (^)(NSDictionary *, NSError *))completion {
// your OP code goes here, e.g.
NSError *error;
NSMutableURLRequest *request = // maybe the param is the url for this request
// use the already initialized session
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// call the completion handler in EVERY code path, so the caller is never left waiting
if (!error) {
// convert the NSData response to a dictionary
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error) {
// there was a parse error...maybe log it here, too
completion(nil, error);
} else {
// success!
completion(dictionary, nil);
}
} else {
// error from the session...maybe log it here, too
completion(nil, error);
}
}];
[postDataTask resume];
}
Code that calls this method will look like this:
// update the UI here to say "I'm busy making a request"
// call your function, which you've given a completion handler
[self makeRequest:#"https://..." completion:^(NSDictionary *someResult, NSError *error) {
// here, update the UI to say "Not busy anymore"
if (!error) {
// update the model, which should cause views that depend on the model to update
// e.g. [self.someUITableView reloadData];
} else {
// handle the error
}
}];
Notice a couple things: (1) the return type is void, the caller expects nothing to be returned from this method, and makes no assignment when calling it. The data "returned" is provided as parameters to the completion handler, which is called later, after the asnych request is complete, (2) the signature of the completion handler matches exactly what the caller declared in the completion block ^(NSDictionary *, NSError *), this is just a suggestion, typical for network requests.
Instantiate the NSURLSession and NSMutableURLRequest object:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"POST"];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"application/json" forHTTPHeaderField:#"Accept"];
Turn your key value pairs into JSON:
// choose the right type for your value.
NSDictionary *postDict = #{#"key1": value1, #"key2": value2};
NSData *postData = [NSJSONSerialization dataWithJSONObject:postDict options:0 error:nil];
Make your POST with with the URL and JSON:
[request setURL:[NSURL URLWithString:#"JSON SERVER"];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
[postDataTask resume];
Parse the JSON data returned within the completionHandler above:
if (!error) {
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
} else {
// error code here
}
responseDict is the parsed data. For example, if the server returns
{
"message":"Your messsage",
"data1":value1,
"data2":value2
}
You can easily get the value for data1 by using
[responseDict objectForKey:#"data1"];
If your want to make another POST with different URL or JSON, just repeat the flow of step 2-4.
Hope my answer helps.

Objective-C issues with dataTaskWithRequest

I have recently switched from sendSynchronousRequest to dataTaskWithRequest
with sendSynchronousRequest my method was working perfectly but when I switch to dataTaskWithRequest I get the following error:
error NSURLError * domain: #"NSURLErrorDomain" - code: 4294966096 0x15ee96c0
and
myError NSError * domain: nil - code: 1684370017 0x26cce125
I don't understand why.
Here is the old code (commented out) and the new code:
/*-(NSDictionary *)GetProductionScheduleData:(NSString *)areaDescription
{
NSString *areaDescriptionWSpaceCharacters = [areaDescription stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSString *requestString = [NSString stringWithFormat:#"%#?areaDescription=%#",kIP,areaDescriptionWSpaceCharacters];
NSURL *JSONURL = [NSURL URLWithString:requestString];
NSURLResponse* response = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:JSONURL];
NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
if(data == nil)
return nil;
NSError *myError;
NSDictionary *productionSchedule = [[NSDictionary alloc]initWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&myError]];
return productionSchedule;
}*/
-(void)GetProductionScheduleData:(NSString *)areaDescription Completetion:(void (^) (NSMutableDictionary * result,NSError * error))completion{
NSString *areaDescriptionWSpaceCharacters = [areaDescription stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSString *requestString = [NSString stringWithFormat:#"%#?areaDescription=%#",kIP,areaDescriptionWSpaceCharacters];
NSURL *JSONURL = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:JSONURL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSError *myError;
NSMutableDictionary *productionSchedule = [[NSMutableDictionary alloc]initWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&myError]];
completion(productionSchedule,myError);
}];
[dataTask resume];
}
Please Help! This was working with sendSynchronousRequest I am starting to dislike dataTaskWithRequest.
The NSURLSession code you have is correct, I confirmed with a valid URL.
You stopped checking to see if data is nil before attempting to JSON parse it. If you add that check back I bet you'll find that there is an error and data is in fact nil.
Change to:
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// handle request error
if (error) {
completion(nil, error);
return;
}
NSError *myError;
NSMutableDictionary *productionSchedule = [[NSMutableDictionary alloc]initWithDictionary:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&myError]];
completion(productionSchedule,myError);
}];
I would recommend also checking myError before attempting to set it to productionSchedule (which could also cause a crash).

Parsing JSON Within JSON in Objective-C

I'm trying to store the JSON that is within the JSON i get from the following request...
NSURL *URL = [NSURL URLWithString:#"http://www.demo.com/server/rest/login?username=admin&password=123"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
// Handle error...
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSLog(#"Response HTTP Status code: %ld\n", (long)[(NSHTTPURLResponse *)response statusCode]);
NSLog(#"Response HTTP Headers:\n%#\n", [(NSHTTPURLResponse *)response allHeaderFields]);
}
NSString* body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response Body:\n%#\n", body);
}];
[task resume];
The resulting JSON obtain from body is the following and as you can see there is a JSON within the JSON, how can I store that JSON in a NSDictionary as you can see that JSON is between quotation marks.
[
{
tag: "login",
status: true,
data:
"
{
"userID":1,
"name":"John",
"lastName":"Titor",
"username":"jtitor01",
"userEmail":"jtitor01#gmail.com",
"age":28,
}
"
}
]
What you have in reality:
Classic JSON, where inside there is a String "representing" a JSON.
So, since we can do:
NSData <=> NSString
NSArray/NSDictionary <=> JSON NSData
We just have to switch between them according to the kind of data we have.
NSArray *topLevelJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *lowLevelString = [[topLevelJSON firstObject] objectForKey:#"data"];
NSData *lowLevelData = [lowLevelString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *final = [NSJSONSerialization JSONObjectWithData:lowLevelData options:0 error:nil];
You should use this line of code
NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData: data options:kNilOptions error:&errorJson];
it will help.thanks
Try this
- (void)loadDetails {
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
_allVehicleLocationsArray = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
[self afterCompleteDoThis];
}] resume];
}
- (void)afterCompleteDoThis {
for (NSDictionary *vehicleDict in _allVehicleLocationsArray) {
NSLog(#" PPP %#" , [vehicleDict valueForKey:#"vehicleType"]);
}
}

Send JSON via HTTP Request via post method

I`m trying to send JSON via HTTP Request:
Here is my code :
NSString* locations = [kBaseURL stringByAppendingPathComponent:kLocations];
BOOL isExistingLocation = location._id != nil;
NSString *urlStr = isExistingLocation ? [locations stringByAppendingPathComponent:location._id] : locations;
NSURL* url = [NSURL URLWithString:urlStr]; //1
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = #"POST";
NSData* data = [NSJSONSerialization dataWithJSONObject:[location toDictionary] options:0 error:NULL]; //3
request.HTTPBody = data;
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"]; //4
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession* session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { //5
if (!error) {
NSLog(#"%#", response.description);
NSArray* responseArray = #[[NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]];
[self parseAndAddLocations:responseArray toArray:self.objects];
}
}];
[dataTask resume];
and here is the dictionary which I`m trying to send...
http://www.imageupload.co.uk/image/5YUE
EDIT: I configured the server to return the HTTPBody received and the return is
{}

Resources