Now, when my app detect that file was updated on server, it download file and user interface stuck for downloading time. I have ASIHTTPRequest wrapper in my app, but I doesn't know how to change my download request to asynchronous.
My code:
- (void)downloadFileIfUpdated
{
NSString *urlString = #"http://www.mysite.com/data.plist";
NSLog(#"Downloading HTTP header from: %#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachedPath = [[documentPaths lastObject] stringByAppendingPathComponent:#"data.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL downloadFromServer = NO;
NSString *lastModifiedString = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"HEAD"];
NSHTTPURLResponse *response;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error: NULL];
if ([response respondsToSelector:#selector(allHeaderFields)]) {
lastModifiedString = [[response allHeaderFields] objectForKey:#"Last-Modified"];
}
NSDate *lastModifiedServer = nil;
#try {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateFormat = #"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
df.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
df.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
lastModifiedServer = [df dateFromString:lastModifiedString];
}
#catch (NSException * e) {
NSLog(#"Error parsing last modified date: %# - %#", lastModifiedString, [e description]);
}
NSLog(#"lastModifiedServer: %#", lastModifiedServer);
NSDate *lastModifiedLocal = nil;
if ([fileManager fileExistsAtPath:cachedPath]) {
NSError *error = nil;
NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:cachedPath error:&error];
if (error) {
NSLog(#"Error reading file attributes for: %# - %#", cachedPath, [error localizedDescription]);
}
lastModifiedLocal = [fileAttributes fileModificationDate];
NSLog(#"lastModifiedLocal : %#", lastModifiedLocal);
[activityIndicator stopAnimating];
}
// Download file from server if we don't have a local file
if (!lastModifiedLocal) {
downloadFromServer = YES;
}
// Download file from server if the server modified timestamp is later than the local modified timestamp
if ([lastModifiedLocal laterDate:lastModifiedServer] == lastModifiedServer) {
[activityIndicator startAnimating];
downloadFromServer = YES;
}
if (downloadFromServer) {
NSLog(#"Downloading new file from server");
NSData *data = [NSData dataWithContentsOfURL:url];
if (data) {
// Save the data
if ([data writeToFile:cachedPath atomically:YES]) {
NSLog(#"Downloaded file saved to: %#", cachedPath);
}
// Set the file modification date to the timestamp from the server
if (lastModifiedServer) {
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:lastModifiedServer forKey:NSFileModificationDate];
NSError *error = nil;
if ([fileManager setAttributes:fileAttributes ofItemAtPath:cachedPath error:&error]) {
NSLog(#"File modification date updated");
[NSThread detachNewThreadSelector:#selector(loadPList) toTarget:self withObject:nil];
[activityIndicator stopAnimating];
}
if (error) {
NSLog(#"Error setting file attributes for: %# - %#", cachedPath, [error localizedDescription]);
}
}
}
}
}
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}];
[request setFailedBlock:^{
NSError *error = [request error];
}];
[request startAsynchronous];
For more details look at http://allseeing-i.com/ASIHTTPRequest/How-to-use#using_blocks
Related
Hi fairly new to iOS just trying to connect the app to an API and get my token using Authentication. I have tried a lot of different options and just can't seem to get my head around it. All i'm trying to do is obtain my token. Can anyone see where I'm going wrong? The API documentation is here: https://simplybook.me/en/api/developer-api
NSURL *url = [NSURL URLWithString:#"http://user-api.simplybook.me/login/"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"myloginname" forHTTPHeaderField:#"X-Company-Login"];
[request setValue:#"mytokenhere" forHTTPHeaderField:#"X-Token"];
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
NSLog(#"%#", resultDict);
} else {
NSLog(#"%#", error);
}
}];
[downloadTask resume];
Instead of declaring NSURLSession like this:
NSURLSession *session = [NSURLSession sharedSession];
Try this instead:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:#"https://user-api.simplybook.me/login/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
And also, make sure you've declared the NSURLSessionDelegate protocol in your header file.
I will give you sample code for getting token but this is regarding to the access and refresh token.You can understand it very clearly now.
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)actionLogin:(id)sender {
[self loginForGettingAccessandRefreshToken];
}
-(void)loginForGettingAccessandRefreshToken
{
#try {
NSString *strUserName = [textUsername.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *strPassword = [textPassword.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString *strParameters = [NSString stringWithFormat:#"client_id=roclient&client_secret=secret&grant_type=password&username=%#&password=%#&scope=dataEventRecords offline_access", strUserName, strPassword];
id param = strParameters;
NSLog(#"The param is - %#",param);
[GlobalShareClass postLoginDataToServer:BASEURL_LOGIN passParameters:param success:^(id res)
{
if([res isKindOfClass:[NSDictionary class]]){
NSDictionary *dictRes = [res copy];
NSString *strErrDesc = [NSString stringWithFormat:#"%#",[dictRes objectForKey:#"error_description"]];
if([[dictRes allKeys] containsObject:#"error_description"]){
dispatch_async(dispatch_get_main_queue(), ^{
//Dispaly UI
});
}
else{
NSString *strAccessToken = [dictRes objectForKey:#"access_token"];
NSString *strRefreshToken = [dictRes objectForKey:#"refresh_token"];
NSString *strTokenType = [dictRes objectForKey:#"token_type"];
NSString *sstrExpiresIn = [dictRes objectForKey:#"expires_in"];
[[NSUserDefaults standardUserDefaults] setObject:globalShare.strRefreshToken forKey:#"refresh_token"];
[[NSUserDefaults standardUserDefaults] setObject:globalShare.strAccessToken forKey:#"access_token"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSDictionary *responseDict = [GlobalShareClass getDataFromToken:globalShare.strAccessToken];
NSString *strFetchedSub = [[NSUserDefaults standardUserDefaults] stringForKey:#"loginIdSub"];
globalShare.loginId = [responseDict objectForKey:#"sub"];
}
}
else{
NSLog(#"The res starts with array");
}
} failure:^(NSError *error) {
// error handling here ...
NSLog(#"%#", [error localizedDescription]);
dispatch_async(dispatch_get_main_queue(), ^{
//Showing Error
});
} passViewController:self];
}
#catch(NSException *exception){
NSLog(#"%#",[exception description]);
}
#finally{
}
}
}
GlobalShareClass.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface GlobalShareClass : NSObject{
NSMutableArray *arr;
}
#property (strong, nonatomic) NSMutableArray *arr;
+ (GlobalShareClass *)sharedInstance;
+ (void)postLoginDataToServer:(NSString *)url passParameters:(id)parameter success:(void (^)(id res))successPost failure:(void(^)(NSError* error))failurePost passViewController:(UIViewController *)vc;
+ (NSDictionary *)getDataFromToken:(NSString *)strToken;
+ (NSDictionary *)urlBase64Decode:(NSString *)strToParse;
#end
GlobalShareClass.m
#import "GlobalShareClass.h"
#implementation GlobalShareClass
#synthesize arr;
+ (GlobalShareClass *)sharedInstance {
static GlobalShareClass* _shareInstane = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shareInstane = [[GlobalShareClass alloc] init];
//Incase array of initialization
_shareInstane.arr = [[NSMutableArray alloc] init];
});
return _shareInstane;
}
+ (void)postLoginDataToServer:(NSString *)url passParameters:(id)parameter success:(void (^)(id res))successPost failure:(void(^)(NSError* error))failurePost passViewController:(UIViewController *)vc{
GlobalShareClass *globalShare = [GlobalShareClass sharedInstance];
__block id jsonResp;
NSData *data = [parameter dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:#"content-type"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *dataTask = [session uploadTaskWithRequest: request
fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(data == nil && error){
NSLog(#"uploadTaskWithRequest error: %#", error);
failurePost(error);
}
else{
jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *strStatusCode = [NSString stringWithFormat:#"%ld",(long)[((NSHTTPURLResponse *)response) statusCode]];
if([strStatusCode isEqualToString:#"400"]){
successPost(jsonResp);
}
NSString *strStatusCodeResponse = [self strGetStatusResponseCode:strStatusCode];
if([strStatusCodeResponse length] > 0){
dispatch_async(dispatch_get_main_queue(), ^{
// Showing error
});
}else{
jsonResp = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if([jsonResp objectForKey:#"error"] || jsonResp == nil){
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertController:#"Error" :[jsonResp objectForKey:#"error_description"] passViewController:vc];
});
}
else
successPost(jsonResp);
}
}
}];
[dataTask resume];
}
+ (NSDictionary *)getDataFromToken:(NSString *)strToken {
NSDictionary *data;
NSString *encoded = [strToken componentsSeparatedByString:#"."][1];
data = [GlobalShareClass urlBase64Decode:encoded];
return data;
}
+ (NSDictionary *)urlBase64Decode:(NSString *)strToParse {
#try {
NSDictionary *returnDict;
NSString *output = [strToParse stringByReplacingOccurrencesOfString:#"-" withString:#"+"];
output = [output stringByReplacingOccurrencesOfString:#"_" withString:#"/"];
switch (output.length % 4) {
case 0:
case 1:
break;
case 2:
output = [output stringByAppendingString:#"=="];
break;
case 3:
output = [output stringByAppendingString:#"="];
break;
default:
break;
}
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:output options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(#"%#", decodedString);
NSData *data = [decodedString dataUsingEncoding:NSUTF8StringEncoding];
returnDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
return returnDict;
}
#catch (NSException *exception) {
NSLog(#"%#", [exception description]);
}
}
#end
In Below code run so i get a response from url but when i try to get encodedPoints it give me a null value. also i update RegexKitLite but prob. not solve. Any suggestion are welcome Thank you advance.
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
// http://maps.googleapis.com/maps/api/directions/json?origin=41.029598,28.972985&destination=41.033586,28.984546&sensor=false%EF%BB%BF%EF%BB%BF
NSURL *apiUrl = [NSURL URLWithString:[apiUrlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:nil error:nil];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
NSLog(#"encodedPoints: %#", encodedPoints);
if (encodedPoints) {
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
else {
return NO;
}
I think its not a good way to do API request synchronously, especially when user' phone has poor internet connection, it will slow down the responsiveness of your application. So you should do an asynchronous API request with NSURLSession.
Also, the Directions API might return more than one routes for your request. So its better to use a NSArray to store your polyline points.
Sample code:
- (void)getPolyline {
NSURL *url = [[NSURL alloc] initWithString:#"https://maps.googleapis.com/maps/api/directions/json?origin=Chicago,IL&destination=Los+Angeles,CA&key=YOUR_API_KEY"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: url];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSError *jsonError;
NSDictionary *dict = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:data options:nil error:&jsonError];
if (!jsonError) {
NSArray *routesArray = (NSArray*)dict[#"routes"];
NSMutableArray *points = [NSMutableArray array];
for (NSDictionary *route in routesArray) {
NSDictionary *overviewPolyline = route[#"overview_polyline"];
[points addObject:overviewPolyline[#"points"]];
}
NSLog(#"%#", points);
}
} else {
//print error message
NSLog(#"%#", [error localizedDescription]);
}
}] resume];
}
I've been having some problems with my AWSS3GetPreSignedURLRequest and AFNetworking's NSMutableURLRequest. I can successfully upload a file with just the Content-Type header. However, if I add the x-amz-acl and the x-amz-server-side-encryption, the upload will fail with 403 - No Permission error. What can I do? Is it an Amazon side problem, using server-side encryption or ACLs isn't allowed with pre-signed URLs, or changing the request will work? I looked pretty deep on the AWS documentation and the iOS SDK reference, but nothing on this. By the way, I'm using AWS iOS SDK v2. Does anyone how how to do this?
NSString *keyName;
NSString *fileContentTypeStr;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM.d.h.mm.ss"];
if([multipleFileType isEqualToString:#"PNG"])
{
fileContentTypeStr = #"image/png";
keyName = [NSString stringWithFormat:#"image_%#.png", [formatter stringFromDate:[NSDate date]]];
}
else if([multipleFileType isEqualToString:#"JPG"])
{
fileContentTypeStr = #"image/jpeg";
keyName = [NSString stringWithFormat:#"image_%#.jpg", [formatter stringFromDate:[NSDate date]]];
}
self.imageUploadURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:#"image"]];
[imageData writeToURL:self.imageUploadURL atomically:YES];
AWSS3GetPreSignedURLRequest *getPreSignedURLRequest = [AWSS3GetPreSignedURLRequest new];
getPreSignedURLRequest.bucket = [NSString stringWithFormat:#"BUCKET-NAME/%#", folderObject.objectId];
getPreSignedURLRequest.key = keyName;
getPreSignedURLRequest.HTTPMethod = AWSHTTPMethodPUT;
getPreSignedURLRequest.expires = [NSDate dateWithTimeIntervalSinceNow:3600];
getPreSignedURLRequest.contentType = fileContentTypeStr;
[[[AWSS3PreSignedURLBuilder defaultS3PreSignedURLBuilder] getPreSignedURL:getPreSignedURLRequest]
continueWithBlock:^id(BFTask *task) {
if (task.error) {
NSLog(#"Error: %#",task.error);
} else {
NSURL *presignedURL = task.result;
NSMutableURLRequest *URLRequest = [NSMutableURLRequest requestWithURL:presignedURL];
[URLRequest setValue:fileContentTypeStr forHTTPHeaderField:#"Content-Type"];
[URLRequest setValue:#"AES-256" forHTTPHeaderField:#"x-amz-server-side-encryption"];
[URLRequest setValue:#"private" forHTTPHeaderField:#"x-amz-acl"];
URLRequest.HTTPMethod = #"PUT";
URLRequest.HTTPBody = imageData;
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSProgress *progress;
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:URLRequest progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if(!error){
NSLog(#"File was successfully uploaded.");
}
}];
[uploadTask resume];
}
return nil;
}];
Note: The code sample there lacks a few things that are on the global headers, and a few other completion blocks + delegates, but I believe everyone will understand the point here.
Anticipated thanks,
As #YosukeMatsuda noticed in comments you can use putObjectAcl: method.
I put ACL for uploaded object on URLSession didCompleteWithError: delegate method like this:
//
self.awss3 = [[AWSS3 alloc] initWithConfiguration:__your_config__];
//
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
if (error)
{
NSLog(#"S3 UploadTask: %# completed with error: %#", task, [error localizedDescription]);
}
else
{
// AWSS3GetPreSignedURLRequest does not contain ACL property, so it has to be set after file was uploaded to bucket
AWSS3PutObjectAclRequest *aclRequest = [AWSS3PutObjectAclRequest new];
aclRequest.bucket = #"your_bucket";
aclRequest.key = #"your_key";
aclRequest.ACL = AWSS3ObjectCannedACLPublicRead;
[[self.awss3 putObjectAcl:aclRequest] continueWithBlock:^id(BFTask *bftask) {
if (bftask.error)
{
NSLog(#"Error putObjectAcl: %#", [bftask.error localizedDescription]);
}
else
{
AWSEndpoint *endpoint = self.awss3.configuration.endpoint;
NSURL *publicReadURL = [[endpoint.URL URLByAppendingPathComponent:backgroundUploadTask.bucket] URLByAppendingPathComponent:backgroundUploadTask.key];
}
return nil;
}];
}
}
We added - setValue:forRequestParameter: to AWSS3GetPreSignedURLRequest. You can use this method to add ACL and encryption headers.
Also, we introduced a new AWSS3TransferUtility for simplifying the background transfer. Refer to our blog post for more details.
I know that use a UIWebview can get title in delegate method webViewDidFinishLoad
But,I want to know if there is a way to only get the title without load the whole webpage?Like http request or something else?
Create url request with asynchronous call to get data from url.
This can be done like this for example:
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
^(NSURLResponse *response, NSData *data, NSError *err) {
// Get Title
NSString *strTitle = #"";
if (data && !err)
{
NSString *returnDataIntoString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//NSLog(#"data : %#",returnDataIntoString);
if (returnDataIntoString.length > 0)
{
NSError *error = nil;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithHTMLString:returnDataIntoString encoding:NSUTF8StringEncoding error:&error];
if (doc && !error) {
NSArray *employees = [doc nodesForXPath:#"//title" error:NULL];
for (GDataXMLElement *employe in employees) {
strTitle = [employe stringValue];
}
}
}
}
else
{
NSLog(#"Error : %#",[err description]);
}
//Set Title here
}];
Note : Now i have used third party library to parse html using GDataXML-HTML
Do you have a whole HTML string? You can using regular expression to parse string if you have it:
NSString *string = #"Your HTML String";
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"<title[^>]*>(.*?)</title>"
options:0
error:&error];
NSTextCheckingResult *result = [regex firstMatchInString:string options:NSMatchingReportProgress range:NSMakeRange(0, [string length])];
NSRange titleRange = [result rangeAtIndex:1];
NSString *title = [string substringWithRange:titleRange];
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]);
}