How to download things without display hanging? - iphone

Okay. So I'm creating this app and I'm really happy with it apart from one thing. It uses a lot of internet database checking etc. and every time it does this it hangs until it has finished, spoiling the fluidity of the interface. Is there anyway to avoid this? Download stuff happens when you click a button or sometimes just as a result of an NSTimer. I would love for the user to be able to go through the interface fluidly and the app to update the info when it gets there. IS there anyway to do this?
EDIT - Current Synchronous code:
This is to download a CSV file:
NSString *link=[[NSString alloc] initWithFormat:#"http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=%#&callback=YAHOO.Finance.SymbolSuggest.ssCallback",timer.userInfo];
NSURL *url=[[NSURL alloc] initWithString:link];
NSData *dl=[[NSData alloc] initWithContentsOfURL:url];
NSString *str = [[NSString alloc] initWithData:dl encoding:NSUTF8StringEncoding];
This is to download a png file into a webView:
NSString *link=[[NSString alloc] initWithFormat:#"http://chart.finance.yahoo.com/z?s=%#&t=GOOG&q=m",self.Input.text];
url=[[NSURL alloc] initWithString:link];
[self.graph loadRequest:[NSURLRequest requestWithURL:url]];

It sounds like you're making synchronous requests. You shouldn't be doing that on the main thread. Your best option is probably to switch to asynchronous requests. You could make synchronous requests on a background thread, but that's more complicated and unnecessary in most situations.

Related

Loading PDF into UIWebView - Anything faster?

I'm doing an application, which loads PDFs from an URL, but is there anything better then using UIWebView? Or any way of loading it page-by-page instead of loading the whole file at once?
I mean it does the job, but it takes 30seconds - 3 minutes to load a PDF on an iPhone 5 while standing NEXT to the router...
I can't imagine what would happen when I ran this code on an iPhone 4 with crappy internet...
Code which does the loading:
CatalogsWebViewController *webViewController = [[CatalogsWebViewController alloc] initWithNibName:#"CatalogsWebView" bundle:nil];
NSString *urlString = [[NSString alloc] initWithFormat:#"http://%#.s3.amazonaws.com/%#",kAmazonAWSBucketName,[catalogs objectAtIndex:indexPath.row]];
NSLog(#"%#",urlString);
webViewController.pdfRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[self.navigationController pushViewController:webViewController animated:YES];
//Here self is webViewController, which got pushed into the navigation controller.
[self.webView loadRequest:self.pdfRequest];
Hum... it turns out, it's not due to the webView, it's cause it takes an immense time to download the file from the S3 bucket. When loading it from [NSBundle mainBundle], it does it it seconds.
As the problem comes from network connectivity, you should display a loading bar while downloading the PDF so the user understands what is going on. Then, upon download completion, save the PDF in the documents folder of your app if the user wants to reopen it later

Update UI when using stringWithContentsofurl

I am using stringWithcontentsofurl to download some strings from my web server to the App, but i would like to update the UI to show A loader of some kind. I am downloading a number of strings (it can be sometimes as much as 100) so it would be neat for the user to show something so they know the App isn't crashing, because now the UI is stuck, i can't show A UILoader or something like that. Is there an option to do so? Or maybe A alternative to stringWithcontentsofurl where this is possible?
greets,
Erik
Try this. It loads stuff in background. If updating the UI later (in asyncload), be sure to do that on main thread.
-(void)loadappdetails:(NSString*)appid {
NSString* searchurl = [#"https://itunes.apple.com/lookup?id=" stringByAppendingString:appid];
[self performSelectorInBackground:#selector(asyncload:) withObject:searchurl];
}
-(void)asyncload:(NSString*)searchurl {
NSURL* url = [NSURL URLWithString:searchurl];
NSError* error = nil;
NSString* str = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (error != nil) {
NSLog(#"Error: %#", error);
}
NSLog(#"str: %#", str);
}
This is a classic case for "Lazy Loading". See Apple's example code:
http://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html
It should be easy to substitute "strings" for "images" as you read that code.
You want to display a placeholder in the label like "(fetching information)" or similar and then load the information in the background, either threading the fetches yourself (asynchronous fetching) or using a library like ASIHTTPRequest that handles all the asynchronous nuts and bolts for you, calling a delegate method once the fetch has completed.
Unfortunately, stringWithContentsOfURL is a synchronous method, meaning it will block your thread and you will not receive any callbacks while it is running. This is also bad for user experience.
The alternative would be to use NSURLConnection to manually setup your own request, and tap into the delegate methods of your connection to display some sort of progress bar. Specifically, you'll want to use connection:didReceiveData: and connectionDidFinishLoading:
Once all the data has been received, use the following to get your string.
NSString *theString = [[NSString alloc] initWithData:yourData encoding:UTF8StringEncoding];
To make this method asynch it is possible and recommendable to use Grand Central Dispatch. If anyone is interested I will show the few lines of code to do that.

run methods in background in iphone

i want to know how to run any method in background...i am making app that parse xml file from internet..the file is large..so it takes 20-25 seconds to parse it and show it in table view...the problem is that when i press the button to parse the file..the button remains pressed until the file is parsed..so upto 20 sec button remains pressed..it looks odd for thr user ..(user thinks like the app hangs..)so my idea is to show the activity indicator and run the parsing method in background...when parsing ends stop the indicator and show the results in table view..any other easy way to implement the same..so that the button does not remain pressed...???
Check out Apple's SeismicXML sample code which uses NSOperation and NSOperationQueue to download and parse XML in a background thread. That way you can see a full implementation working in the context of an actual application.
Threading
Create the new thread:
[NSThread detachNewThreadSelector:#selector(myParse) toTarget:self withObject:nil];
Create the method that is called by the new thread:
- (void)myParse {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
*** code that should be run in the new thread goes here ***
//sample
NSURL *url;
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
resourcePath = [resourcePath stringByAppendingPathComponent:#"sample.xml"];
url = [[NSURL fileURLWithPath:resourcePath] retain];
[self parsingTheXMLAtUrl:url];
[pool release];
}
see iphone sdk example for more information.
All the best.

iphone asynchronous file load?

is there way to load local files in iphone asynchronously? I load uiimages for my uitableview using this:
NSData *imageData = [[NSData alloc] initWithContentsOfFile:fileName];
UIImage *cachedImage = [[[UIImage alloc] initWithData:imageData] autorelease];
but it is slow, because main thread is locked or something until NSData finishes loading the file and UI becomes unresponsive. Is there something like NSURLConnection but for local files? So I can just load file without freezing UI, and when it finishes loading, some handler sends notification or something like that.
You can use an NSOperationQueue and NSInvocationOperation to call a 'load' procedure. Then, from the load procedure, simply use the 'performSelectorOnMainThread' to update. See: http://gist.github.com/375559 for a detailed example.

How can I create a single HTTP Get request for iPhone?

First of all, sorry for my posibly bad english...
I got a surely big stupid question...
In my enterprise have an automatic door system, that is opened with a HTTP GET request to a file.
Example:
http://ipaddress/rc.cgi?o=1,50
Where the o=number indicates the amount of seconds that the automatic door will run.
The is no need for authentification or nothing (that is made by LAN Radius).
So, the question is...
How can I make a single button (for example in the springboard) that when you touch it, runs the GET request?
You thing that it should be possible with NSURLConection ?
Thanks for all
I'm not sure if this is the best way of going about it, but this is how I've achieved something similar in my own app. Just create a new NSData object that hits the required URL, then release it if you don't need to do anything with the returned data:
NSURL *theURL = [[NSURL alloc] initWithString:#"http://ipaddress/rc.cgi?o=1,50"];
NSData *theData = [[NSData alloc] initWithContentsOfURL:theURL];
[theData release];
[theURL release];
Or just create an NSURLConnection to run asynchronously, then you don't have to worry about the UI hanging and if the delegate is set to nil, you can pretty much forget about it after you've run it.
NSURL * url = [NSURL URLWithString:#"http://ipaddress/rc.cgi?o=1,50"];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:url];
NSURLConnection * theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:nil];
[request release];
[theConnection release];