iOS async task freezes - ios

I have an app which does an async post to a server. Then it decodes the json and returns the message from the server. I put a few debugging log entries in my code, so I know that the response from the server, as well as the decoding of the json are instantaneous. The problem is that after the json is decoded, the async task runs for about 6 seconds before it calls the next event (Showing the popup dialog).
- (IBAction)register:(id)sender {
[self startPost]; // Starts spinner animation
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self doPost]; // performs post
});
}
-(void)doPost
{
#try {
NSString *post =[[NSString alloc] initWithFormat:#"request=register&platform=ios&email=%#&password=%#",self.email.text,self.password.text];
//NSLog(#"PostData: %#",post);
NSURL *url=[NSURL URLWithString:#"https://site.com/api.php"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
//[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//NSLog(#"Response code: %d", [response statusCode]);
if ([response statusCode] >=200 && [response statusCode] <300)
{
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
//NSLog(#"Response ==> %#", responseData);
NSData *responseDataNew = [responseData dataUsingEncoding:NSUTF8StringEncoding];
NSError* error = nil;
NSDictionary *myDictionary = [NSJSONSerialization JSONObjectWithData:responseDataNew options:NSJSONReadingMutableContainers error:&error];
if ( error ){
[self alertStatus:#"Unknown response code from server" :#"Whoops!"];
NSLog(#"Response ==> %#", responseData);
[self postDone];
}else{
if ([myDictionary[#"error"] isEqualToNumber:(#1)])
{
NSLog(#"ERROR DETECTED");
[self alertStatus:myDictionary[#"message"]:#"Whoops!"];
[self postDone];
}
else
{
[self alertSuccess];
[self postDone];
}
}
} else {
if (error) NSLog(#"Error: %#", error);
[self alertStatus:#"Connection Failed" :#"Whoops!"];
[self postDone];
}
}
#catch (NSException * e) {
NSLog(#"Exception: %#", e);
[self alertStatus:#"Registration Failed." :#"Whoops!"];
[self postDone];
}
}
-(void)startPost
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
self.email.enabled = false;
self.password.enabled = false;
self.confirm.enabled = false;
self.cancelButton.enabled = false;
}
- (void) alertStatus:(NSString *)msg :(NSString *)title
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:msg
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alertView setTag:0];
[alertView show];
}
- (void) alertSuccess
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Success!"
message:#"You have been successfully registered."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alertView setTag:1];
[alertView show];
}
-(void)postDone
{
self.registerButton.hidden = false;
self.spinner.hidden = true;
self.loadingText.hidden = true;
//[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
self.email.enabled = true;
self.password.enabled = true;
self.confirm.enabled = true;
self.cancelButton.enabled = true;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{if (alertView.tag == 1)
{
[self dismissViewControllerAnimated:YES completion:nil];
}}
The alertStatus and alertSuccess functions just pop up a message box briefly.
When I run the code, I purposefully enter bad information so the log says "ERROR DETECTED". The problem is that it takes another 6 seconds before anything happens after that.

After you have called:
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
and obtained the data, you should switch back to the main thread to use it. This is because all UI updates must be done on the main thread.
So, all that code after you get the data should be moved to a new method and called as:
dispatch_async(dispatch_get_main_queue(), ^{
[self handleData:urlData withResponse:response error:error];
}
And you should also put the exception catch code inside dispatch_async(dispatch_get_main_queue(), ^{ because you try to update the UI there too...

Related

Getting (null) on the first element in JSON

I want to log the first element with his subject. If I call the method using [self doRequest] in viewDidload, it works perfectly.
But if I call the method in a if- statement, it returns (null).
Code:
//Do request method
NSString *host = #"api.blazor.nl";
if(![host hasPrefix:#"http://"] || ![host hasPrefix:#"https://"])
{
host = [#"http://" stringByAppendingString:host];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#", host]] cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
[request setHTTPMethod:#"GET"];
NSString *publickey = [[NSUserDefaults standardUserDefaults]
stringForKey:#"publicKey"];
NSString *privatekey = [[NSUserDefaults standardUserDefaults]
stringForKey:#"privateKey"];
NSLocale* currentLocale = [NSLocale currentLocale];
NSString* currentTime = [[NSDate date] descriptionWithLocale:currentLocale];
[request setValue:currentTime forHTTPHeaderField:#"x-api-time"];
[request setValue:publickey forHTTPHeaderField:#"x-api-public"];
[request setValue:privatekey forHTTPHeaderField:#"x-api-private"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLSessionDataTask *urlSessionDataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error)
{
NSLog(#"%#", error);
dispatch_async(dispatch_get_main_queue(), ^{
[self.activityIndicator stopAnimating];
UIAlertController *alertViewController= [UIAlertController alertControllerWithTitle:#"An error happened" message:nil preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:#"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}];
[alertViewController addAction:closeAction];
[self presentViewController:alertViewController animated:YES completion:nil];
});
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSInteger success = 1;
NSError *serializeError = nil;
NSDictionary *jsonData2 = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&serializeError];
success = [jsonData2[#"ERROR"] integerValue];
if((long)[httpResponse statusCode] == 200){
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"logged_in"];
}
if (success == 0) {
NSLog(#"%#", jsonData2[#"notifications"][0][#"thread"][#"subject"]);
NSLog(#"%#", jsonData2);
NSLog(#"%ld", (long)[httpResponse statusCode]);
}else{
}
}];
[urlSessionDataTask resume];
//if statement
if(count < someNumber) {
[self doRequest];
[[NSUserDefaults standardUserDefaults] setObject:someNumber forKey:#"count"];
} else {
NSLog(#"Number not samller then someNumber");
}
}
//Json:
notifications = (
{
content = "has quoted you in";
created = "2017-06-22T12:12:04+00:00";
id = "68b87954-77ae-4202-bb2f-2417a974fa57";
"reply_id" = 79811;
thread = {
id = 3294;
subject = "Ik erger me aan..... deel 2";
};
"thread_id" = 3294;
"users_from" = {
username = Moe;
};
}
);
}
What's wrong with the code?
Thanks.

NSURLConnection method needs to be changed to pass authentication challenge

i have a method for http connection, which was working fine for me until the server i am trying to have an invalid ssl certificate.
Since i am using
[NSURLConnection sendSynchronousRequest:returningResponse:error]
There is no chance to pass authentication challenge by using NSURLConnection delegate methods.
Now, i need to change my service call code as fast as possible.
My method returns the data received from the connection, that is the major problem i can not easily change mine to
NSURLConnection to initWithRequest:delegate:
My service call method is as follows;
-(id)serviceCall:(NSString*)str withURL:(NSString*)serviceUrl withIdentifier:(NSString*)type
{
globalURL = [[NSURL alloc] initWithString:serviceUrl];
shouldAllowSelfSignedCert = YES;
// if(ISDEBUG) NSLog(#"%#",serviceUrl);
NSMutableDictionary* json;
NSURLResponse* response;
NSData* responseData = [NSMutableData data];
NSError* error = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:globalURL];
[request setHTTPMethod:#"POST"];
[request setHTTPBody: [str dataUsingEncoding: NSUTF8StringEncoding]];
NSString* msgLength = [[NSString alloc] initWithFormat:#"%lu", (unsigned long)[str length]];
[request addValue:#"text/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request addValue:msgLength forHTTPHeaderField:#"Content-Length"];
request.timeoutInterval = 180;
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if([type isEqualToString:#"image"])
{
if(ISDEBUG) NSLog(#"%#",responseData);
return responseData;
}
else
{
if(error)
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NO_WS_CONNECTION message:#"" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
if(ISDEBUG) NSLog(#"%#",error);
}
else
{
if(responseData !=nil)
{
json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:NO_WS_CONNECTION delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
}
}
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if(ISDEBUG) NSLog(#"%#",responseString);
}
return json;
}
I hope i am clear enough.
What is your advise?
Thanks.
You should have a good reason to do it synchronously, so, I will try to help you without changing the flow.
Try wrapping the request into a class where you can implement the request using initWithRequest:delegate: and make the class return the response using block.
You will have something like:
[YourRequestClass requestWithURL:serviceURL callback:^(NSData *yourData, NSError *error){
}];
Ok, at this point you have a new tool that makes ASYNCHRONOUS requests, make the authentication challenge stuff for you and returns the result on a block.
Now, you can simply use dispatch_semaphore to block your thread until the request returns a response ....
-(id)serviceCall:(NSString*)str withURL:(NSString*)serviceUrl withIdentifier:(NSString*)type {
__block NSData *myData = nil;
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[YourRequestClass requestWithURL:serviceUrl callback:^(NSData *yourData, NSError *error){
//ignoring error (this is an example !)
myData = yourData;
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
//Use myData and make yourObject here!
return yourObject;
}
Note that It's just an example, and I'm just trying to pointing you the right way ... I didn't test this code, but I believe it should work as expected!

AFNetworking - AFHTTPRequestOperation in a for loop (array enumeration)?

I am using AFNetworking, (AFHTTPRequestOperation) to make calls to the network and get the data back. I need to make use of the code in a for loop (enumeration of cards) to check for each card and get the data back, if the operation is successful, I get the information about the cards and if it fails, I should get an alert (using an alert view). The problem is I am getting multiple alerts if it fails (because it's inside a for loop and there can be a number of cards). How can I just show one alert only when it fails to connect to the network?
I know the operation is async, but can't get this to work.
Code below:-
- (void)verifyMobileDeviceStatus
{
[self fetchRequest];
[self.contentsArray enumerateObjectsUsingBlock:^(GCards *gCard, NSUInteger idx, BOOL * stop) {
NSURL *baseURL = nil;
baseURL = [NSURL URLWithString:BASE_URL_STRING];
NSString *soapBody = [NSString stringWithFormat:#"<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?><soapenv:Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Header/><soapenv:Body><VerifyMobileDeviceStatus xmlns=\"http://tempuri.org/\"><Request><AuthToken>%#</AuthToken></Request></VerifyMobileDeviceStatus></soapenv:Body></soapenv:Envelope>", [gCard valueForKey:#"authToken"]];
NSLog(#" auth token =%#", [gCard valueForKey:#"authToken"]);
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:baseURL];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapBody length]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[soapBody dataUsingEncoding:NSUTF8StringEncoding]];
[request addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[request addValue:#"http://tempuri.org/VerifyMobileDeviceStatus" forHTTPHeaderField:#"SOAPAction"];
[request addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"success: %#", operation.responseString);
NSString *xmlString = [operation responseString];
[parser setGCard:gCard];
[parser parseXML:xmlString];
if([gCard.merchantStatus isEqualToString:MERCHANT_STATUS_ACTIVE])
{
gCard.isPremiumAccount = [NSNumber numberWithInt:1];
}
else
{
gCard.isPremiumAccount = [NSNumber numberWithInt:0];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[parser.delegate verifyDeviceStatusParserDidFailWithError:#"Error"];
NSLog(#"error: %#", [error userInfo]);
}];
[operation start];
}];
}
- (void)verifyDeviceStatusParserDidFailWithError:(NSString *)error
{
NSString *errorString = [NSString stringWithFormat:#"Error =%#", [error description]];
NSLog(#"Error parsing XML: %#", errorString);
BlockAlertView* alert = [BlockAlertView alertWithTitle:#"Connection Failed" message:#"Connection to web service Failed. Please try again."];
[alert addButtonWithTitle:NSLocalizedString(#"OK", nil) block:^{ }];
[alert show];
[activityIndicator stopAnimating];
self.navigationController.view.userInteractionEnabled = YES;
}
It's showing the alert multiple times, if it fails and I need to show it only once.
Any help would be appreciated.
You need to make the alert view a property of the class, so.
1 - Declare a property (alert) of type BlockAlertView in the class that make the multiple requests (let's call it RequesterClass). This property will reference an unique alert view, which will be displayed only once.
2 - Put this 2 lines in the init method of the RequesterClass
_alert = [BlockAlertView alertWithTitle:#"Connection Failed" message:#"Connection to web service Failed. Please try again."];
[_alert addButtonWithTitle:NSLocalizedString(#"OK", nil) block:^{ }];
3 - Modify the verifyDeviceStatusParserDidFailWithError: as follows:
- (void)verifyDeviceStatusParserDidFailWithError:(NSString *)error
{
NSString *errorString = [NSString stringWithFormat:#"Error =%#", [error description]];
NSLog(#"Error parsing XML: %#", errorString);
if(!alert.visible)
{
[alert show];
}
[activityIndicator stopAnimating];
self.navigationController.view.userInteractionEnabled = YES;
}
Hope it helps!

Why loading data Indicator is not working properly?

In my code I am using an UIActivityIndicatorView on an UIAlertView. It is working fine but my problem is it is not showing up on correct time. I mean to say when the device get data from web service after that this loading indicator is appearing in the end and its not rite thing I think because I want it to be appear when the web service is sending or receiving data.
I need help as I am new to iOS app development. If there is any other easy way to do this thing then suggest me.
I hope my question is clear, my problem is according to this code the loading indicator is appearing after i get reply from web service but i want to run this indicator as the user will press update button and web service should be called after that. Tell me where i am wrong.
Here is the code I am using
-(IBAction)update:(id)sender
{
av=[[UIAlertView alloc] initWithTitle:#"Updating Image..." message:#"" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
ActInd=[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[ActInd startAnimating];
[ActInd setFrame:CGRectMake(125, 60, 37, 37)];
[av addSubview:ActInd];
[av show];
{
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
int gid=[defaults integerForKey:#"gid"];
NSString *gameid=[NSString stringWithFormat:#"%i", gid];
NSLog(#"%#",gameid);
img=mainImage.image;
NSData *imgdata=UIImagePNGRepresentation(img);
NSString *imgstring=[imgdata base64EncodedString];
NSLog(#"%#",imgstring);
NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)imgstring,
NULL,
CFSTR("!*'();:#&=+$,/?%#[]"),
kCFStringEncodingUTF8);
NSLog(#"escapedString: %#",escapedString);
#try
{
NSString *post =[[NSString alloc] initWithFormat:#"gid=%#&image=%#",gameid,escapedString];
NSLog(#"%#",post);
NSURL *url=[NSURL URLWithString:#"http://mywebspace/updategameimage.php"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Response code: %d", [response statusCode]);
if ([response statusCode] >=200 && [response statusCode] <300) {
NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Response ==> %#", responseData);
SBJsonParser *jsonParser = [SBJsonParser new];
NSDictionary *jsonData = (NSDictionary *) [jsonParser objectWithString:responseData error:nil];
NSLog(#"%#",jsonData);
NSInteger type = [(NSNumber *)[jsonData objectForKey:#"type"] integerValue];
NSLog(#"%d",type);
if (type==1) {
[self alertStatus:#"You can Keep on Drawing" :#"Sketch Updated"];
}
}
}
#catch (NSException * e) {
NSLog(#"Exception: %#", e);
[self alertStatus:#"Unable to connect with game." :#"Connection Failed!"];
}
}
[av dismissWithClickedButtonIndex:0 animated:YES];
[av release]; av=nil;
}
UI updates are done on main thread. You have started activity indicator on main thread.It's fine.
Now, you are making synchronous network call on main thread. It should be asynchronous. Here until you will receive the response from network call, your main thread will remain busy and your UI will not be updated.
To update the UI, you can either make the network call asynchronous or you can start the activity indicator in a separate function and then delay the call of network activity by performselector:afterdelay method.
You can use GCD, Raywenderlich Tutorial
-(IBAction)update:(id)sender
{
/*
Setup indicator and show it
*/
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
/*
Do network call
*/
dispatch_async(dispatch_get_main_queue(), ^{
/*
Update UI
*/
});
});
}

ASIHTTPRequest set Download Destination Path failing

I have a method which looks for a certain pdf, if it doesn't find it locally it uses ASIHTTPRequest to download it asynchronously. However the request always fails when the line:
[request setDownloadDestinationPath:currentDetailItem];
is uncommented, the request starts and the progress increases until 100% then the request failed block is executed.
These are the relevant NSLogs when the request fails:
2012-08-16 12:08:34.398 XXXX[1675:707] Request started with url :http://XXXX.com/gwas/sites/default/files/Responding%20to%20Severe%20Weather%20Events.pdf
filePath :/var/mobile/Applications/322C24CF-9664-403D-9CC5-13C396F39F84/Documents/Responding%20to%20Severe%20Weather%20Events.pdf
2012-08-16 12:08:39.018 XXXX[1675:707] Request failed:HTTP/1.1 200 OK
Here is the code for the method:
- (void)setDetailItem:(NSString *)newDetailItem {
NSArray *downloadPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSArray *components = [newDetailItem componentsSeparatedByString:#"/"];
NSString *filePath = [[downloadPaths objectAtIndex:0] stringByAppendingFormat:#"/%#", [components lastObject]];
currentDetailItem = filePath;
if (![self fileExistsLocally:[components lastObject]]) {
//Download the file
[self displayProgressView];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:newDetailItem]];
[request setDownloadDestinationPath:currentDetailItem];
[request setDownloadProgressDelegate:progressBar];
[request setCompletionBlock:^
{
[self showPdf:currentDetailItem];
[self hideProgressView];
NSLog(#"%f, Request finished :%#", progressBar.progress, request.responseStatusMessage);
}];
[request setFailedBlock:^
{
NSLog(#"Request failed:%#", request.responseStatusMessage);
[self hideProgressView];
[SVProgressHUD showErrorWithStatus:#"Request failed"];
}];
[request startAsynchronous];
NSLog(#"Request started with url :%#\nfilePath :%#", newDetailItem, currentDetailItem);
}
else {
[self showPdf:currentDetailItem];
}
}
If I comment the line [request setDownloadDestinationPath:currentDetailItem]; out, the request is successful. Any ideas? thanks!
For anyone who is interested, I fixed the problem by swapping over to NSURLConnection, here's the code:
- (void)setDetailItem:(NSString *)newDetailItem {
NSArray *downloadPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSArray *components = [newDetailItem componentsSeparatedByString:#"/"];
NSString *filePath = [[downloadPaths objectAtIndex:0] stringByAppendingFormat:#"/%#", [components lastObject]];
currentDetailItem = filePath;
if (![self fileExistsLocally:[components lastObject]]) {
[self displayProgressView];
data_ = [[NSMutableData alloc] init];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:newDetailItem] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
if (!connection) {
[SVProgressHUD showErrorWithStatus:#"Request failed"];
return;
}
else {
data_ = [[NSMutableData alloc] init];
}
}
else {
[self showPdf:currentDetailItem];
}
}
#pragma mark NSURLConnectionDelegate methods
- (void)connection: (NSURLConnection*) connection didReceiveResponse: (NSHTTPURLResponse*) response
{
if ([response statusCode] == 200) {
currentDownloadSize = [response expectedContentLength];
}
[data_ setLength:0];
}
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data
{
[data_ appendData:data];
progressBar.progress = ((float) [data_ length] / (float) currentDownloadSize);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//Save file locally
NSURL *url = [NSURL fileURLWithPath:currentDetailItem];
NSError *error = nil;
[data_ writeToURL:url options:0 error:&error];
if (error) {
NSLog(#"Write failed with error:%#", error);
}
else {
NSLog(#"Request successful");
[self showPdf:currentDetailItem];
}
[self hideProgressView];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[self hideProgressView];
[SVProgressHUD showErrorWithStatus:#"Request failed"];
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

Resources