NSURLSessionDataTask completion handler not getting called for the first time - ios

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-type"];
[request setHTTPBody:jsonData];
// configure NSURLSessionConfiguration with request timeout
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
// set request timeout
defaultConfigObject.timeoutIntervalForRequest = 120.0;
// create NSURLSession object
// Working fine with below instance of default session but its taking a lot of time to fetch response.
//NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
// set NSURLSessionDataTask
#try {
NSURLSessionDataTask * dataTask = [defaultSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//
}];
[dataTask resume];
}

The task never completes because it never gets started. You have to manually start the data task using its resume() method.
And Don't use the dataTask object inside the try block.

if ([self checkNetworkStatus]) {
#try {
// Create the data and url
NSString *encryptedString = [self createRequest:userContext objectType:deviceObjectType projectType:projectId];
NSDictionary *dictRequest = #{REQ_KEY_REQUEST: encryptedString};
requestString = [JSONHelper dictionaryToJson:dictRequest];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#Data",globals.API_Base_URL]];
// Create Request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
request.HTTPMethod = #"POST"; // For Post
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
int strLength = (int)requestString.length;
[request setValue:[NSString stringWithFormat:#"%d", strLength] forHTTPHeaderField:#"Content-Length"];
NSData *dataRequest = [requestString dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = dataRequest;`enter code here`
id delegateValue = self;
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:delegateValue
delegateQueue:[NSOperationQueue mainQueue]];
//NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:
^(NSData *responseData, NSURLResponse *response, NSError *error) {
// ...
[self destroyNetworkCache];
// [[NSURLCache sharedURLCache] storeCachedResponse:nil forRequest:urlReq];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
dispatch_async(dispatch_get_main_queue(), ^(void)
{
if (! error)
{
[self parseResponse:responseData forObjectType:deviceObjectType andTag:tag withDelegate:del];
}
else
{
NSString *errMsg = error.description;
if (errMsg.length <= 0) {
errMsg = NSLocalizedString(#"msg_network_error", #"msg_network_error");
}
else if (errMsg.length > 0 && [errMsg rangeOfString:#"timed out"].length != 0)
{
errMsg = NSLocalizedString(#"msg_request_timed_out", #"msg_request_timed_out");
}
else if ([self checkForURLDomainError:errMsg])
{
errMsg = NSLocalizedString(#"msg_network_error", #"msg_network_error");
}
if (tag < 0)
{
if ([del conformsToProtocol:#protocol(WTConnectionServiceDelegate)])
{
if ([del respondsToSelector:#selector(wtConnectionService:forObjectType:didFailedWithError:)])
{
[del wtConnectionService:nil forObjectType:deviceObjectType didFailedWithError:errMsg];
return;
}
}
}
else
{
if ([del conformsToProtocol:#protocol(WTConnectionServiceDelegate)])
{
if ([del respondsToSelector:#selector(wtConnectionService:forObjectType:andTag:didFailedWithError:)])
{
[del wtConnectionService:nil forObjectType:deviceObjectType andTag:tag didFailedWithError:errMsg];
return;
}
}
}
}
});
}];
[task resume];
}
#catch (NSException *exception) {
[self handleException:exception];
}
#finally {
}
}
Below Is delegate methods
-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
-(void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error{
}

Related

how to call again same APIs when response is other then status code 200 or error (some time)

i am using APIs call in my iPhone (objective C) app. my APIS call returns Status code 200, but some time it does return 405 response. when i restart my app i do get proper response.
how to call back same API when i get other then 200 response or if i get error...so that i don't have to restart app again.
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *authValue = [NSString stringWithFormat:#"Bearer %#",
[arrTokenData valueForKey:#"Token"]];
//Configure session with common header fields
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = #{#"Authorization": authValue};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSString *url = #"http://test.myserver.am/api/mobile/LookUps/getuserdata";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
//Process the data
}
else if
{
// how to call back same API
}
}
else
{
// how to call back same API
}
}];
[task resume];
Thanks in advance
I considered as you created a generic method of network call. If you will get an error or other than 200 response. Just take the request details from your request and call that generic method with that request(URL).
Sample code:
NSURLSessionDataTask *DataTask = [session dataTaskWithRequest:theRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSHTTPURLResponse *serverResponse = (NSHTTPURLResponse*)response;
if (error == nil) {
if (serverResponse.statusCode == 200) {
NSString *theXML = [[NSString alloc] initWithBytes:
[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
NSLog(#"%#", theXML);
} else {
NSLog(#"%#, %#", serverResponse.URL, serverResponse.allHTTPHeaderFields);
//Call the generic network call method with the above details again
}
} else {
NSLog(#"%#", error. localizedDescription);
NSLog(#"%#, %#", serverResponse.URL, serverResponse.allHTTPHeaderFields);
//Call the generic network call method with the above details again
}
}];
[DataTask resume];
Create new thread and execute the failed requests.
Create one method and write your code in that method and call same method on error like below
- (void)callService {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSString *authValue = [NSString stringWithFormat:#"Bearer %#",
[arrTokenData valueForKey:#"Token"]];
//Configure session with common header fields
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPAdditionalHeaders = #{#"Authorization": authValue};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSString *url = #"http://test.myserver.am/api/mobile/LookUps/getuserdata";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
//Process the data
}
else
{
// how to call back same API
[self callService];
}
}
else
{
// how to call back same API
[self callService];
}
}];
[task resume];
}

Trying to understand asynchronous calls

I have this method
- (NSString*) createUserWithName:(NSString*)TheName
{
NSURL *URL =someUrlthatIncludesTheName
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sharedSession];
NSURL *URL = [NSURL URLWithString:url];
NSURLSessionTask *task = [session dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (response) {
NSError* error = nil;
NSArray *output = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
myID = [[output objectAtIndex:0] objectForKey:#"UserID"];
}
}];
[task resume];
return myID;
}
and another method
-(void)doSomethingWith: (NSString*) anID
Somewhere in my code, I call these methods subsequently, like this:
[self createUserWithName:#"John"];
[self doSomethingWith:myID];
However, due to the fact that the NSURLSession in createUserWithName: is asynchronous, doSomethingWith: is fired with myID = (null).
What is the best way to approach this problem, without necessarily falling back to deprecated synchronous NSURLConnection?
Thanks in advance
The workflow is supposed to be
- (void)createUserWithName:(NSString*)TheName
{
NSURL *URL =someUrlthatIncludesTheName
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sharedSession];
NSURL *URL = [NSURL URLWithString:url];
NSURLSessionTask *task = [session dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (response) {
NSError* error = nil;
NSArray *output = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
myID = [[output objectAtIndex:0] objectForKey:#"UserID"];
[self doSomethingWith:myID];
}
}];
[task resume];
}
And the call is just
[self createUserWithName:#"John"];
The method doSomethingWith: is asynchronously executed in the completion block.
Alternatively use a custom completion block
- (void)createUserWithName:(NSString *)theName completion:^(NSString *identifier)completion
{
NSURL *URL =someUrlthatIncludesTheName
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sharedSession];
NSURL *URL = [NSURL URLWithString:url];
NSURLSessionTask *task = [session dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (response) {
NSError* error = nil;
NSArray *output = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
myID = [[output objectAtIndex:0] objectForKey:#"UserID"];
completion(myID);
}
}];
[task resume];
}
and call it with
[self createUserWithName:#"John" completion:^(NSString *identifier) {
[self doSomethingWith:identifier];
}];

Rest call from webViewDidFinishLoad cause error

When i call getProfile method from viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
[self getProfile];
}
it success
-(void)getProfile
{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSString *tempurl= [NSString stringWithFormat:#"%#11155/person/#self",baseUrlSecure];
tempurl = [tempurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:tempurl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:gWCToken forHTTPHeaderField:#"WCToken"];
[request addValue:gWCTrustedToken forHTTPHeaderField:#"WCTrustedToken"];
[request setHTTPMethod:#"GET"];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error)
{
NSLog(#"Error: %#", error);
dispatch_async(dispatch_get_main_queue(), ^{
[Alert showAlertWithTitle:#"M2All" andWithMessage:error.localizedDescription onView:self andErrorCode:[NSString stringWithFormat:#"%ld",error.code]];
});
}
else
{
NSDictionary *dictResult = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray *arrError = [dictResult objectForKey:#"errors"];
if(arrError.count >0)
{
dispatch_async(dispatch_get_main_queue(), ^{
[Alert showAlertWithTitle:#"M2All" andWithMessage:[[arrError objectAtIndex:0] objectForKey:#"errorMessage"] onView:self andErrorCode:[[arrError objectAtIndex:0] objectForKey:#"errorCode"]];
});
return;
}
}
}];
[postDataTask resume];
}
but same calling from webViewDidFinishLoad then getting error
i don't know what is the problem
- (void)webViewDidFinishLoad:(UIWebView *)webView{
[self getProfile];
}
Clear the browser cookies and try again. I faced the similar problem. I cleared the browser cache and it's working fine for me

Need to post array of values in a url objective c

Hi am new to development I need to post the below array in a url kindly guide me to solve this issue.
{
"order": {
"email": "foo#example.com",
"fulfillment_status": "fulfilled",
"send_receipt": true,
"send_fulfillment_receipt": true,
"line_items": [
{
"variant_id": 447654529,
"quantity": 1
}
]
}
}
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
[sessionConfiguration setAllowsCellularAccess:YES];
[sessionConfiguration setHTTPAdditionalHeaders:#{ #"Accept" : #"application/json" }];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSString *datastring = #"{\"order\": {\"email\": \"foo#example.com\",\"fulfillment_status\": \"fulfilled\",\"send_receipt\":true,\"send_fulfillment_receipt\": true,\"line_items\": [{\"variant_id\": 447654529,\"quantity\": 1}]}}";
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"YOUR LINK"]];
NSLog(#"url=%#",url);
// Configure the Request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [datastring dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = #"POST";
// post the request and handle response
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
// Handle the Response
if(error)
{
NSLog(#"%#",[NSString stringWithFormat:#"Please check your internet connection: %#", [error description]]);
// Update the View
dispatch_async(dispatch_get_main_queue(), ^{
// Hide the Loader
// [MBProgressHUD hideHUDForView:[[UIApplication sharedApplication] delegate].window animated:YES];
[self ShowConnectionError];
});
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
NSString *retVal = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"retVal=%#",retVal);
});
}];
// Initiate the Request
[postDataTask resume];

Perform a HTTP POST request and then a HTTP GET request

I am a beginner in handling connections in iOS. I want to perform a POST request and a GET request to a url. The thing is that I need to first do the POST so I can get an access token parsed in a JSON that later will place in the header of the GET request, so I can retrieve the login data I need. I am using custom delegate methods, but when I run this, the GET request is performed earlier than the POST, so I cannot get the key before the GET is done. Is there any way to perform the POST first and then the GET? Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//params
self.user = #"carlos";
self.pass = #"1234";
self.grantType = #"password";
self.clientId = #"7da713e69afc96cf894e";
self.clientSecret = #"2c14ec54cfdfd6faec4ef56ca7f0870ab83f820b";
// Set the side bar button action. When it's tapped, it'll show up the sidebar.
self.sideBarButton.target = self.revealViewController;
self.sideBarButton.action = #selector(revealToggle:);
// Set the gesture
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
[self httpPostWithCustomDelegate];
[self sendHTTPGet];
}
-(void) httpPostWithCustomDelegate
{
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
NSURL * url = [NSURL URLWithString:#"http://192.237.241.175:8090/oauth2/access_token/"];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
NSString * params =[NSString stringWithFormat:#"&username=%#&password=%#&grant_type=%#&client_id=%#&client_secret=%#&scope=write",self.user,self.pass,self.grantType,self.clientId,self.clientSecret];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(#"Retrieving Data");
// NSLog(#"Response:%# %#\n", response, error);
if(error == nil)
{
//Test Display
// NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
// NSLog(#"Data = %#",text);
self.responseDataPost = [[NSMutableData alloc] init];
[self.responseDataPost appendData:data];
NSError *error;
NSMutableDictionary *receivedData = [NSJSONSerialization JSONObjectWithData:self.responseDataPost options:NSJSONReadingMutableContainers error:&error];
//obtener del dictionary el access token y meter como header Authorization Bearer + id
//NSArray *accessToken = [receivedData valueForKeyPath:#"access_token"];
self.connTxtPost.text = [receivedData valueForKeyPath:#"access_token"];
self.recData = [receivedData valueForKeyPath:#"access_token"];
}
}];
[dataTask resume];
}
-(void) sendHTTPGet
{
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
NSURL * url = [NSURL URLWithString:#"http://192.237.241.175:8090/snippets/"];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:#"GET"];
self.connTxtGet.text = self.recData ;
[urlRequest setValue:self.recData forHTTPHeaderField:#"Authorization"];
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
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);
}
}];
[dataTask resume];
}
You don't need to call these two method all together.
[self httpPostWithCustomDelegate];
[self sendHTTPGet];
You are making two request at the same time. But which response will come first you can not determine it. As you need data from "POST" request to make the "GET" request. Do something like this:
-(void) httpPostWithCustomDelegate{
.............
NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
...................
...................
self.connTxtPost.text = [receivedData valueForKeyPath:#"access_token"];
self.recData = [receivedData valueForKeyPath:#"access_token"];
[self sendHTTPGet];
}
}];
[dataTask resume];
}
This will make sure when you make the "GET" request you have the "access_token". Hope this will work just fine. :)

Resources