ASIHTTPRequest don't save pdf file when the delegate set - ios

I try to download a pdf from server and this is my code
ASIHTTPRequest *req = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:[GlobalMethod convertURL:[NSString stringWithFormat:#"%#%#",SITE_IMAGE_URL,pview.nameLable.text]]]];
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// Add your filename to the directory to create your saved pdf location
NSString *pdfLocation = [documentDirectory stringByAppendingPathComponent:#"test.pdf"];
// TEMPORARY PDF PATH
// Get the Caches directory
NSString *cachesDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// Add your filename to the directory to create your temp pdf location
NSString *tempPdfLocation = [cachesDirectory stringByAppendingPathComponent:#"test.pdf"];
req.shouldContinueWhenAppEntersBackground = YES;
req.delegate = self;
req.downloadProgressDelegate = pview.progressView;
[req setDidFinishSelector:#selector(requestDone:)];
[req setDidFailSelector:#selector(requestWentWrong:)];
[req setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:pview.nameLable.text,REQ_FILE_NAME, nil]];
[req setTemporaryFileDownloadPath:tempPdfLocation];
[req setDownloadDestinationPath:pdfLocation];
[req startAsynchronous];
it didn't save file to the destination path when the delegate set to self but it work correctly when I comment this line
req.delegate = self;
I really need the delegate to be set
what should I do ?

I found the problem and solve it. It's all happened because of a simple if else. In
ASIHTTPRequest.m
in
-(void)handleBytesAvailable
method you have this code in
// Does the delegate want to handle the data manually?
if (dataWillBeHandledExternally) {
NSData *data = nil;
if ([self isResponseCompressed] && ![self shouldWaitToInflateCompressedResponses]) {
data = inflatedData;
} else {
data = [NSData dataWithBytes:buffer length:bytesRead];
}
[self performSelectorOnMainThread:#selector(passOnReceivedData:) withObject:data waitUntilDone:[NSThread isMainThread]];
// Are we downloading to a file?
}else if ([self downloadDestinationPath]) {
BOOL append = NO;
if (![self fileDownloadOutputStream]) {
if (![self temporaryFileDownloadPath]) {
[self setTemporaryFileDownloadPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]];
} else if ([self allowResumeForFileDownloads] && [[self requestHeaders] objectForKey:#"Range"]) {
when you delete the else before the second if and change it to
// Does the delegate want to handle the data manually?
if (dataWillBeHandledExternally) {
NSData *data = nil;
if ([self isResponseCompressed] && ![self shouldWaitToInflateCompressedResponses]) {
data = inflatedData;
} else {
data = [NSData dataWithBytes:buffer length:bytesRead];
}
[self performSelectorOnMainThread:#selector(passOnReceivedData:) withObject:data waitUntilDone:[NSThread isMainThread]];
// Are we downloading to a file?
}if ([self downloadDestinationPath]) {
BOOL append = NO;
if (![self fileDownloadOutputStream]) {
if (![self temporaryFileDownloadPath]) {
[self setTemporaryFileDownloadPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]];
} else if ([self allowResumeForFileDownloads] && [[self requestHeaders] objectForKey:#"Range"]) {
it work correctly with delegate and also save to this

Related

iOS 9 Making Code go Sequentially (Touch ID)

I am a developer using self-taught Objective-C to code for the iPhone. We are using Xcode 7 and iOS 9. I am tasked with creating an app for my company to communicate when someone arrives and leaves an appointment in a schedule made for them (using XML).
We would like to use Touch ID for security so the users don’t have to log in a lot. Security is required because of the confidentiality of the data in the app. I had the application working. Or it looked like it worked, until I clicked on the Cancel option in Touch ID and realized that the Touch ID was providing no security.
I believe this is because the methods that are supposed to run after Touch ID were outside of the LA Context block. I put them outside because I need to return a string value on a successful authorization (an internal employee number retrieved through XML). If I put the methods with the returned NSStrings outside of the LA Context block, the methods run in the wrong order.
How can I make the following 4 methods run in sequential order?
1)requireLogin (Touch ID code here)
2)requestSession
3)readSession
4)checkSession
If the Touch ID fails, methods 2-4 should not run.
I’ve looked at blocks. I’ve looked at GCD. I can’t find any examples on how to deal with this. If someone could point me in the right direction. I would really appreciate it. If I need to include more of the code, please let me know.
Thank you in advance.
- (NSString *)retrieveESN {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [directoryPaths objectAtIndex:0];
NSString *fullPath = [documentsDirectoryPath stringByAppendingString:#"/session.txt"];
if ([fileManager fileExistsAtPath:fullPath]==YES) {
_finished = false;
NSLog(#"File exists");
[self readSession];
NSLog(#"%#", _sessionDetail);
NSLog(#"Pre Check Session");
NSString *result = [self checkSession:_sessionDetail];
NSLog(#"Post Check Session");
NSLog(#"%#", result);
if ([result isEqualToString:#"Error"]) {
NSLog(#"Error received - going into newFile");
NSString *userESN = [self newFile];
NSLog(#"Error'd returning with result");
NSLog(#"UserESN: %#", userESN);
return userESN;
} else {
NSLog(#"No Error Received");
NSLog(#"Returning result: %#", result);
return result;
}
} else {
_finished = false;
NSLog(#"No file exists, call newFile");
NSString *userESN = [self newFile];
NSLog(#"UserESN: %#", userESN);
return userESN;
}
}
- (NSString *)newFile {
NSLog(#"File does not exist.");
[self requireLogin];
NSLog(#"Out of requireLogin");
[self requestSession];
NSLog(#"Out of requestSession");
[self readSession];
NSLog(#"Out of readSession");
NSString *userESN = [self checkSession:_sessionDetail];
NSLog(#"Into checkSession again newfile");
return userESN;
}
- (void)requireLogin {
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;
NSLog(#"Into requireLogin");
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
// Authenticate User
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:#"You must log in to the app."
reply:^(BOOL success, NSError * _Nullable error) {
if (success) {
_finished = true;
NSLog(#"success");
} else {
switch (error.code) {
case LAErrorAuthenticationFailed:
NSLog(#"Authentication Failed");
break;
case LAErrorUserCancel:
NSLog(#"User pressed Cancel button");
break;
case LAErrorUserFallback:
//Return to go to Enter Password not available screen.
NSLog(#"User pressed Enter Password");
break;
default:
NSLog(#"Touch ID is not configured");
break;
}
NSLog(#"Authentication Fails");
}
}];
} else {
NSLog(#"Phone doesn't support Touch ID.");
}
}
- (void)requestSession {
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSString *url = #“https://companyurl.com/session_page”;
NSLog(#"Got to requestSession");
NSMutableString *postText = [[NSMutableString alloc] init];
NSLog(#"%#", idfv);
[postText appendString:idfv];
NSString *postBody = [NSString stringWithString:postText];
XMLPostSecurity *postAction = [[XMLPostSecurity alloc] init];
NSLog(#"Got to PostAction");
_sessionDetail = [postAction sendPostRequestToUrl:url withBody:postBody];
NSLog(#"Session Detail: %#", _sessionDetail);
FileSaving *saver = [[FileSaving alloc] init];
[saver saveSession:self.sessionDetail];
NSLog(#"Saved file.");
}
-(NSString *)readSession {
NSLog(#"In to readSession.");
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [directoryPaths objectAtIndex:0];
NSString *fullPath = [documentsDirectoryPath stringByAppendingString:#"/session.txt"];
while ([fileManager fileExistsAtPath:fullPath]==NO);
NSFileManager *fileManagerTwo;
NSData *dataBuffer;
fileManagerTwo = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingString:#"/session.txt"];
NSLog(#"Got Path");
dataBuffer = [fileManagerTwo contentsAtPath:filePath];
NSLog(#"databuffer created");
_sessionDetail = [[NSString alloc] initWithData:dataBuffer encoding:(NSASCIIStringEncoding)];
NSLog(#"File read: %#", _sessionDetail);
return _sessionDetail;
}
-(NSString *)checkSession:(NSString *)sessionFound {
NSLog(#"Into checkSession");
NSDictionary *cookieProperties = [NSDictionary dictionaryWithObjectsAndKeys:
#"ollie/", NSHTTPCookieDomain,
#"\\", NSHTTPCookiePath,
#"cookieName", NSHTTPCookieName,
sessionFound, NSHTTPCookieValue,
nil];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
NSArray *cookieArray = [NSArray arrayWithObject:cookie];
NSDictionary *headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArray];
NSMutableString *url = [[NSMutableString alloc] initWithString:#“https://companyurl.com/xmlfile.php”];
NSLog(#"%#", url);
NSURL *urlNew = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlNew];
[request setHTTPMethod:#"GET"];
[request setAllHTTPHeaderFields:headers];
self.parseData = NULL;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(#"dataTaskWithRequest error: %#", error);
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(#"dataTaskWithRequest HTTP status code: %ld", (long)statusCode);
if (statusCode == 401) {
// Insert process for thumbprint and session cookie pull
NSLog(#"401 Error received");
NSFileManager *fileManagerThree = [NSFileManager defaultManager];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *sessionPath = [documentsPath stringByAppendingPathComponent:#"session.txt"];
NSError *error;
BOOL success = [fileManagerThree removeItemAtPath:sessionPath error:&error];
if (success) {
NSLog(#"File deleted - check session.");
} else {
NSLog(#"File could not be deleted.");
}
} else {
NSLog(#"I got something other than 200 or 401");
return;
}
}
}
self.parseData = data;
}];
[task resume];
while ( self.parseData == NULL );
ParseTypeXML *myParser = [[ParseTypeXML alloc] initWithData:self.parseData];
if ([myParser.esn count] == 0) {
return #"Error";
} else {
return myParser.esn[0];
}
}

UIScrollView dynamic contents not appearing

I'm having a trouble dynamically adding UIButtons with background image as subviews to a UIScrollView. Its kind of a image gallery using UIButtons on a scrollView. I have used this method for couple of my apps, it works fine for me with the static contents.
But this time, Im loading images from a web service and saved to documents directory, then call the method to create the gallery. Logic is same with my other apps. But I cannot figure out what is the issue here.
I'll put here both the codes one is for retrieving data and other is the creating gallery.
Data retrieving from server
-(void)loadDataFromServer{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
arrCats = [[NSMutableArray alloc]init];
arrPromos = [[NSMutableArray alloc]init];
//[spinMenu startAnimating];
// load promo images from the server
for(int i=0;i<[arrPromos count];i++)
{
NSString *urlString = [Constants getImages:[[arrPromos objectAtIndex:i] objectForKey:#"image"]];
NSLog(#"Get Images API Call : %#", urlString);
NSURL *imageurl = [NSURL URLWithString:urlString];
//get a dispatch queue
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//this will start the image loading in bg
dispatch_async(concurrentQueue, ^{
NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageurl];
//this will set the image when loading is finished
dispatch_async(dispatch_get_main_queue(), ^{
if(imageData != nil){
// save the images temporally
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:[[arrPromos objectAtIndex:i] objectForKey:#"image"]]; //Add the file name
[imageData writeToFile:filePath atomically:YES];
}
});
});
}
// Load promotions from server
dispatch_async(queue, ^{
NSLog(#"Promotions Loading Started");
NSString *urlString = [Constants getAllPromotions:#"GetPromo.php"];
NSLog(#"Get Promotions API Call : %#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Specify that it will be a GET request
request.HTTPMethod = #"GET";
[request setHTTPShouldHandleCookies:NO];
NSURLResponse *responseURL;
NSError *error;
NSData *dataPromotions = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseURL error:&error];
if (responseURL == nil)
{
// Check for problems
if (error != nil)
{
NSLog(#"Get Promtions Connection failed! Error - %#", [error localizedDescription]);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Connection Error!" message:#"Promotions data failed to load!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
else
{
NSString *responseString = nil;
responseString = [[NSString alloc] initWithData:dataPromotions encoding:NSUTF8StringEncoding];
if ([responseString rangeOfString:#"error"].location == NSNotFound)
{
NSDictionary *response = [[NSDictionary alloc] init];
response = (NSDictionary *)[responseString JSONValue];
NSLog(#"Response : Promotions %#", response);
if(response != Nil){
if([response count]>0){
arrPromos = [NSMutableArray arrayWithArray:[response objectForKey:#"Promos"]];
NSLog(#"ArrPromos # loading %#", arrPromos);
// create promos galley
[self createPromosGallery];
}
}
}
}
});
Note: [self createPromosGallery]; is calling after download all the images and data.
Create Gallery
-(void) createPromosGallery{
// sort arrPromos based on priority
for(int i=0; i<[arrPromos count];i++){
[arrPromos sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSDictionary *dict1 = obj1;
NSDictionary *dict2 = obj2;
NSString *string1;
NSString *string2;
if(![[dict1 objectForKey:#"priority"] isKindOfClass: [NSNull class]])
string1 = [dict1 objectForKey:#"priority"];
if(![[dict2 objectForKey:#"priority"] isKindOfClass: [NSNull class]])
string2 = [dict2 objectForKey:#"priority"];
return [string1 compare:string2 options:NSNumericSearch];
}];
}
NSLog(#"ArrPromos %#", arrPromos);
// scrollView size
CGFloat screenHieght = [UIScreen mainScreen].bounds.size.height;
if(screenHieght>500){
scrollView.frame = CGRectMake(0, 0, 320, 568);
}
else{
scrollView.frame = CGRectMake(0, 0, 320, 480);
}
// define scrollview height
int scrollHieght;
scrollHieght = ([arrPromos count]-1)/2;
NSLog(#"Scroll height %d",scrollHieght);
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width , scrollHieght * 160 +200);
scrollView.pagingEnabled = NO;
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.showsVerticalScrollIndicator = NO;
scrollView.scrollsToTop = NO;
scrollView.decelerationRate = UIScrollViewDecelerationRateFast;
scrollView.delegate = self;
for(int i=0;i<[arrPromos count];i++)
{
float x;
float y;
if(i%2==0)
{
x=30.0;
y=(i/2)*160+25;
}
if(i%2==1) {
x=170.0;
y=(i/2)*160+25;
}
// retreive saved images
NSString *strImgName;
UIImage *buttonUpImage;
// create buttons
button = [UIButton buttonWithType:UIButtonTypeCustom];
strImgName = [[arrPromos objectAtIndex:i] objectForKey:#"image"];
NSLog(#"Button image name %#", strImgName);
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/%#",docDirectory,strImgName];
buttonUpImage = [UIImage imageWithContentsOfFile:filePath];
[button setBackgroundImage:buttonUpImage forState:UIControlStateNormal];
button.frame = CGRectMake(x, y, 120,140);
[button setTag:i];
[button addTarget:self action:#selector(promoBtnPressed:)forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:button];
}
}
Note: I tested on both iOS 7 and 6. In iOS 7, it takes very long time to appear images on scrollView(Currently have only 2 images). Or else, If I TAP on scroolView then the images appear.
In ios 6, nothing appear
//Make a method that has url (fileName) Param
NSArray *documentsDirectory =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:url];
NSFileManager *fileManager =[NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:textPath])
{
return YES;
}
else
{
return NO;
}
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage
imageNamed:#""]];//Placeholder image
if ([url isKindOfClass:[NSString class]])
{
imgView.image = [UIImage imageNamed:[url absoluteString]];
imgView.contentMode = UIViewContentModeScaleAspectFit;
}
else if ([fileManager fileExistsAtPath:url])
{
NSString *textPath = [documentsDirectory stringByAppendingPathComponent:url];
NSError *error = nil;
NSData *fileData = [NSData dataWithContentsOfFile:textPath options:NSDataReadingMappedIfSafe error:&error];
if (error != nil)
{
DLog(#"There was an error: %#", [error description]);
imgView.image=nil;
}
else
{
imgView.image= [UIImage imageWithData:fileData]
}
}
else
{ UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
CGPoint center = imgView.center;
// center.x = imgView.bounds.size.width / 2;
spinner.center = center;
[spinner startAnimating];
[imgView addSubview:spinner];
dispatch_queue_t downloadQueue = dispatch_queue_create("iamge downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
[spinner removeFromSuperview];
UIImage *image = [UIImage imageWithData:imgData];
NSError *error = nil;
[imgData writeToFile:url options:NSDataWritingFileProtectionNone error:&error];
if (error != nil)
}
else
{
}
imgView.image = image;
});
});
}
Thats UIImageView loading an image if it doesnot exist in document then it Save it , An Activity indicator is added to show image is loading to save,
Yes it is because you are downloading and then saving the images which takes time. I suggest you to use any library for downloading images and saving them.
Ex : SDWebImage

Background thread confusion

I'm trying to improve the responsiveness of my app but am a complete newbie to threading and have become confused.
On launch an alert is shown:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSString *user = [[alertView textFieldAtIndex:0] text];
NSString *pass = [[alertView textFieldAtIndex:1] text];
[self loginToServerWithUsername:user andPassword:pass];
}
}
within the loginToServerWithUsername: method, the app calls a method:
[self checkFiles:sessionID];
This can take several seconds so I tried to execute it in the background:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self checkFiles:sessionID];
});
checkFiles method:
fileList = [[NSMutableString alloc] init];
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [directoryPaths objectAtIndex:0];
NSString *downloadsFolderString = [documentsDirectory stringByAppendingPathComponent:DOWNLOADS_FOLDER];
NSError *error = nil;
NSString* file;
NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:downloadsFolderString];
while (file = [enumerator nextObject])
{
BOOL isDirectory = NO;
[[NSFileManager defaultManager] fileExistsAtPath: [NSString stringWithFormat:#"%#/%#",downloadsFolderString,file]
isDirectory: &isDirectory];
if (!isDirectory)
{
[fileList appendString:[NSString stringWithFormat:#"%#|", file]];
}
}
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd/MM/yyyy HH:mm"];
NSString *timeOpened = [formatter stringFromDate:[NSDate date]];
NSString *post = [NSString stringWithFormat:#"sessionID=%#&fileList=%#&dateTime=%#&userID=%#", sessionID, fileList, timeOpened, userID];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSString *comparisonURLString = SERVER_COMPARE_URL_STRING;
NSURL *comparisonURL = [NSURL URLWithString:comparisonURLString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:comparisonURL];
[request setHTTPMethod:#"POST"];
[request addValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSHTTPURLResponse *urlResponse = nil;
error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
if (responseData)
{
NSString *requiredFilesList = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSArray *lines = [requiredFilesList componentsSeparatedByString: #"\n"];
if (lines.count > 2)
{
dispatch_async(dispatch_get_main_queue(), ^(void){
NSRange theRange;
theRange.location = 2;
theRange.length = [lines count] -3;
numberOfFilesToBeDownloaded = theRange.length;
if (numberOfFilesToBeDownloaded <= 0)
{
_jobStatusLabel.text = #"Documents up to date"; // is this the issue?
}
if (numberOfFilesToBeDownloaded > 0)
{
NSArray *subArray = [lines subarrayWithRange:theRange];
[self animateProgressBar];
if (![eraseDevice isEqualToString:#"true"])
{
[self getFiles:subArray];
}
}
});
}
}
else
{
NSLog(#"no response data from check files");
}
However, the alertView is not dismissed until the checkFiles method is complete.
Can anyone tell me how to have the alert dismiss whilst checkFiles runs in the background?
The UI operations should be done in the main thread.
For instance :
_jobStatusLabel.text = #"Documents up to date"; // is this the issue?
should be
dispatch_async(dispatch_get_main_queue(), ^(void){
_jobStatusLabel.text = #"Documents up to date"; // is this the issue?
});
change all such possible cases.
Obviously you are updaing UI elemets from background thread. This would lead to unpredictable behavior. A better way to do this is like this -
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_async(queue, ^{
[self checkFiles:sessionID];
dispatch_async(dispatch_get_main_queue(),^{
//breakup your checkFiles method to background tasks & UI tasks. Put UI updating
//code here which will get executed in the main thread.
});
});
This is the GCD pattern of coding. Here it is asynchronous thread executes code synchronously. i.e. after checkFiles finishes the next code (here its a async thread) gets executed.
You would need to break checkFiles method. Execute the HTTP part in the background thread and pass the parsed responseData to main UI thread. After that update the UI. See if this works...

download multiple images in iOS App

I want to download multiple images from URL to my device in iOS App.
//
// ImageDownload.m
//
#import "ImageDownload.h"
#implementation ImageDownload {
int *position;
NSArray *downloableImages;
}
- (void)start:(NSArray *)images delegate:(id)delegate
{
position = 0;
downloableImages = images;
NSUInteger *count = ((NSUInteger *)[downloableImages count]);
NSLog(#"%d", count);
[self startDownload];
}
- (void)startDownload
{
NSUInteger *imageDataCount;
NSArray *image;
NSString *filename;
NSString *fileurl;
NSURLRequest *imageUrlRequest;
image = [downloableImages objectAtIndex:position];
NSLog(#"%d", position);
NSArray *imageData = [image valueForKey:#"image"];
imageDataCount = ((NSUInteger *)[imageData count]);
if (imageDataCount > 0) {
filename = [imageData objectAtIndex:0];
fileurl = [imageData objectAtIndex:1];
NSLog(#"%#", fileurl);
imageUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:fileurl]];
NSURLConnection *imageUrlConnection = [[NSURLConnection alloc] initWithRequest:imageUrlRequest delegate:self startImmediately:TRUE];
} else {
NSUInteger *count = ((NSUInteger *)[downloableImages count]);
if (((NSUInteger *)position) < ((NSUInteger *)count - 1)) {
position = position + 1;
[self startDownload];
}
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"finish image...");
NSUInteger *count = ((NSUInteger *)[downloableImages count]);
if (((NSUInteger *)position) < ((NSUInteger *)count - 1)) {
position = position + 1;
[self startDownload];
}
}
#end
For now... I only check the position of the download and current URL,
Exists 27 files to download... but the download not go one by one... check this output:
Position: 0
http.....fichero00.jpg
Finish download
Position: 4
http.....fichero04.jpg
Finish download
Position: 8
http.....fichero08.jpg
Finish download
Create an ivar NSOperationQueue *operationQueue; in your .h file and init it in your .m file:
operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 1;
For downloading images, create a method that takes an image URL and call it for each image:
-(void)downloadImageAtURL:(NSURL *)imageURL {
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:imageURL] queue:operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// Do something with your images here...
};
}
You can try this code.. Its 100 % Working for me
You can get more reference here
-(IBAction)startdownload
{
for (int i=0; i<[downloadarray count]; i++) //download array have url links
{
NSURL *URL = [NSURL URLWithString:[downloadarray objectAtIndex:i]];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc]initWithURL:URL];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if([data length] > 0 && [[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"])
{
//make your image here from data.
UIImage *imag = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [array objectAtIndex:0];
NSString *imgstr=[NSString stringWithFormat:#"%d",i];
NSString *pngfilepath = [NSString stringWithFormat:#"%#sample%#.png",docDir,imgstr];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(imag)];
[data1 writeToFile:pngfilepath atomically:YES];
}
else if ([data length] == 0 && [[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"])
{
NSLog(#"No Data!");
}
else if (![[NSString stringWithFormat:#"%#",error] isEqualToString:#"(null)"]){
NSLog(#"Error = %#", error);
}
}];
}
-(IBAction)viewfile
{
NSMutableArray *arr=[[NSMutableArray alloc]init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pngfilepath = [NSString stringWithFormat:#"%#",documentsDirectory];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:pngfilepath error:&error];
for (int i=0; i<[filePathsArray count]; i++){
NSString *pngfilepath = [NSString stringWithFormat:#"%#%#",documentsDirectory, [filePathsArray objectAtIndex:i]];
[arr addObject:[UIImage imageWithContentsOfFile:pngfilepath]];
}
myimageview = [[UIImageView alloc] initWithImage:[arr objectAtIndex:0]]; //Here myimageview is UIImageView
}
Hope This Helps!!!
Work around NSOperationQueue it allow you to control how much operation are run concurrently.
Create:
NSOperationQueue *queue = [NSOperationQueue new];
queue.maxConcurrentOperationCount = 1;
Then add operations :
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
... here is you code with converting image to data and addition it to NSURLConnection
}];
[operation setCompletionBlock:^{
....something that you want to do, after operation completes
}];
[queue addOperation:operation];
More about NSOperation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/cl/NSOperation
Here is my new code...
I have a delay when I try to update a UIProgressView
//
// ImageDownload.m
//
#import "ImageDownload.h"
#implementation ImageDownload {
NSMutableArray *downloableImages;
int position;
Sync *mySync;
}
- (void)start:(NSArray *)images sync:(Sync *)sync
{
NSArray *imageData;
int imageDataCount;
mySync = sync;
downloableImages = [[NSMutableArray alloc] init];
for (NSArray *image in images) {
imageData = [image valueForKey:#"image"];
imageDataCount = [imageData count];
if (imageDataCount > 0) {
[downloableImages addObject:imageData];
}
}
[self downloadAllFiles];
}
- (void)downloadAllFiles
{
NSString *filename;
NSString *fileUrl;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cacheDirectory = [paths objectAtIndex:0];
position = 0;
int count = [downloableImages count];
NSLog(#"%#", downloableImages);
NSLog(#"total files %d", count);
for (NSArray *image in downloableImages) {
filename = [image objectAtIndex:0];
fileUrl = [image objectAtIndex:1];
NSURL *url = [NSURL URLWithString:fileUrl];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
position++;
float progress = (float)position / (float)count;
//update UIProgressView
[mySync setProgressImageDownload:progress];
if ([data length] > 0 && [[NSString stringWithFormat:#"%#", error] isEqualToString:#"(null)"]) {
UIImage *downloadedImage = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
NSString *imageDestinationPath = [NSString stringWithFormat:#"%#%#", cacheDirectory, filename];
NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(downloadedImage, 100.0)];
[imageData writeToFile:imageDestinationPath atomically:YES];
}
if (position == count) {
NSLog(#"all complete...");
[mySync downloadImagesComplete];
}
}];
}
}
#end

QLPreviewController not opening downloaded file

I'm trying to preview a downloaded file to system and the program crashes when performing the method called previewController:previewItemAtIndex:. From what I assumed is that is releasing the previewcontroller before it is displayed, but this error does not occur when the file is already in the documents folder. It only happens when trying to open the file right after it has been downloaded.
Here is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSUInteger count = [listSessionsST count];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Signature *object = [listSessionsST objectAtIndex:row];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UILabel *lblInComplete = (UILabel*)[cell viewWithTag:4];
UIImageView *imgCheck = (UIImageView*)[cell viewWithTag:3];
//Sets the File Name
self.File = [[[NSString stringWithFormat:#"%#_%#.%#",object.FileName,object.ModDate,object.Extension]
componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceCharacterSet]] componentsJoinedByString: #""];
//Shows the loading screen while the file is being downloaded
[DejalBezelActivityView activityViewForView:self.view withLabel:#"Downloading" width:0 LoadingType:#"Full"];
[DejalActivityView currentActivityView].showNetworkActivityIndicator = YES;
//Calls the method that will begin downloading the file
[self performSelector:#selector(startDownload:) withObject:object.Location afterDelay:0.2];
}
- (void)startDownload:(NSString *)strLocation{
NSString *filePath = [NSString stringWithFormat:#"%#/tmp/%#", NSHomeDirectory(),self.File];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if (fileExists)
{
[DejalBezelActivityView removeViewAnimated:YES];
//QuickLook APIs directly to preview the document
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
[[self navigationController] pushViewController:previewController animated:YES];
[previewController release];
}
else
{
NSDictionary *dictionary = [Signature downloadFile:self.File Path:strLocation];
if ([dictionary valueForKey:#"Error"] == nil)
{
//If no error has occurred while downloading then preview the file.
//QuickLook APIs directly to preview the document
QLPreviewController *previewController = [[QLPreviewController alloc] init];
previewController.dataSource = self;
previewController.delegate = self;
[[self navigationController] pushViewController:previewController animated:YES];
[previewController release];
[DejalBezelActivityView removeViewAnimated:YES];
}
else
{
//If an error occurred while downloading then display message to user.
[DejalBezelActivityView removeViewAnimated:YES];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#""
message:[dictionary valueForKey:#"Response"]
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
[alert release];
}
}
}
// Returns the number of items that the preview controller should preview
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)previewController{
return 1;
}
// returns the item that the preview controller should preview
- (id)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index{
NSString *path = [NSString stringWithFormat:#"%#/tmp/%#", NSHomeDirectory(),self.File];
return [NSURL fileURLWithPath:path];
}
The method that downloads the file and saves it to the tmp folder
---------------------------------------------------------------
+ (NSDictionary *)downloadFile:(NSString *)strFile Path:(NSString *)strPath{
float freeSpace = 0.0f;
NSError *error = nil;
NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[NSString stringWithFormat:#"%#/tmp", NSHomeDirectory()]
error: &error];
if (dictionary)
{
NSNumber *fileSystemFreeSizeInBytes = [dictionary objectForKey: NSFileSystemFreeSize];
freeSpace = [fileSystemFreeSizeInBytes floatValue];
}
else
{
//Handle error
NSLog(#"Error;%#",error);
return [NSDictionary dictionaryWithObjectsAndKeys:#"An error has occurred while downloading the file.",#"Response",#"Y",#"Error", nil];
}
if (freeSpace > 0.0f)
{
NSDictionary *dict = nil;
BOOL blnHasErroroccurred = NO;
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *encoded = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)strPath,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]%",
kCFStringEncodingUTF8 );
NSString *strURL = [NSString stringWithFormat:#"%#/DataTransfer/DownloadFile?EMP_ID=%#&FilePath=%#",
appDelegate.ServerAddress,
appDelegate.UserId,
encoded];
[encoded release];
NSURL *url = [NSURL URLWithString:strURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLResponse* response = nil;
NSError* resultError = nil;
NSData* dataResult = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&resultError];
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
if ([httpResponse statusCode] == 200)
{
#try
{
if (dataResult.length < freeSpace)
{
//Get the tmp directory
NSFileManager *fileManager =[NSFileManager defaultManager];
NSString *fileName = [NSString stringWithFormat:#"%#/tmp/%#", NSHomeDirectory(),strFile];
//Write the data to using the tmp directory
BOOL filecreationSuccess = [fileManager createFileAtPath:fileName contents:dataResult attributes:nil];
if(filecreationSuccess == YES)
{
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"",#"Response",nil,#"Error", nil];
}
else
{
blnHasErroroccurred = YES;
}
}
}
#catch (NSException *exception)
{
blnHasErroroccurred = YES;
}
}
else
{
blnHasErroroccurred = YES;
}
if(blnHasErroroccurred == YES)
{
dict = [NSDictionary dictionaryWithObjectsAndKeys:#"An error has occurred while downloading the file.", #"Response", #"Yes",#"Error",nil];
}
[dataResult release];
return dict;
}
else
{
return [NSDictionary dictionaryWithObjectsAndKeys:#"Not enough disk space to download file.",#"Response",#"Y",#"Error", nil];
}
}

Resources