How to send downloading process as a background process - iphone

I am downloading data from my server it is taking like 5 to 6 minutes for downloading..while downloading I am not able to do any work in my application. How to send downloading process on background so that user can navigate within application and after download. we will inform user downloading completed..
Thank you.

Create the new thread:
[NSThread detachNewThreadSelector:#selector(myMethod)
toTarget:self
withObject:nil];
Create the method that is called by the new thread:
- (void)myMethod
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
/*** code that should be run in the new thread goes here ***/
[pool release];
}
What if you need to do something to the main thread from inside your new thread (for example, show a loading symbol)? Use performSelectorOnMainThread.
[self performSelectorOnMainThread:#selector(myMethod)
withObject:nil
waitUntilDone:false];

What you need to do is have your downloading code on a separate thread (NSThread on iOS). Here's a tutorial to get you started.

Related

threading for network calls in iOS 5

I have been looking over the internet, but could not find the perfect tutorial for threading in iOS, currently i am working on iOS 5 , tutorial found on web were old, my app needs to fetch data from webservices, so I want to call network operation in a thread, I have a tabbar, in each tab it loads different type of data from web, as it start fetching data , I dont want my app to stuck on that tab, i want that user can navigate to other tab meanwhile its fetching data for that tab. how can it be possible
EDIT: I want to have a flow :
//in a thread
fetchDataFromWeb(){//during this call activity indicator
//fetch and make an array of ojbects
}
when data is loaded trigger the populate funciton
laoddata(){//remove activity indicator
//load tableview and other views
}
how will i know my thread finished its process
Take a look to NSOperation, NSThread or Grand Central Dispatch
Edit: NSThread example
//on main thread on some action
NSDictionary *myParameterDitionary = [..];
[NSThread detachNewThreadSelector:#selector(aBackThreadMethod:) toTarget:self withObject:myParameterDitionary];
//this is on back thread called
- (void)aBackThreadMethod:(NSDictionary *)variablesDictionary{
#autoreleasepool {
//presess data
NSDictionary *responseDictionary = [..];
[self performSelectorOnMainThread:#selector(didABackThreadMethod:) withObject:responseDictionary waitUntilDone:YES];
}
}
//call back on main thread
- (void)didFinishABackThreadMethod:(NSDictionary *)responseDictionary{
//do stuff ex update views
}
The #autoreleasepool is for ARC. If you use manual memory management you have to do:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[pool release];

How to get notified about imageWithContentsOfFile: completion?

I load a huge-huge image with imageWithContentsOfFile:, so I have to set up an activityIndicator during the process.
Is there any way/any delegate callback I can use to be informed about the end of this loading process?
imageWithContentsOfFile is synchronous.
You could start an activity indicator, load your big image into memory in a background thread and then go back to the main thread and stop the indicator.
- (void)loadBigImage {
[activityIndicator startAnimating];
[self performSelectorInBackground:#selector(loadBigImageInBackground) withObject:nil];
}
- (void)loadBigImageInBackground {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
UIImage *img = [UIImage imageWithContentsOfFile:#"..."];
[self performSelectorOnMainThread:#selector(bigImageLoaded:) withObject:img waitUntilDone:NO];
[pool release];
}
- (void)bigImageLoaded:(UIImage *)img {
[activityIndicator stopAnimating];
// do stuff
}
Short answer: Nope. sorry!
Long answer :
You could open the file in a background process (an NSOperation?) bit by bit using C style methods i.e. fopen, fread etc) and fire notifications back to the main thread during the load. Then create the image and fire a notification that the image is ready?
If you want to have a delegate & be informed of the progress of the load, you can use an NSURLConnection instead of the synchronous imageWithContentsOfFile.
There's an example of this in the Apple URL Loading System Programming Guide
Your NSURLConnection delegate didReceiveData: method could append the incoming data to an NSData object, then you would use UIImage imageWithData: to create them image once everything's downloaded.
This gives you the most flexibility/control over monitoring the progress of the load; although if all you're trying to do is avoid hanging the UI while the image downloads, simply using imageWithContentsOfFile in a background thread may be easier.

Cannot post to twitter via Twitter-OAuth-iPhone in a NSThread

I recently started using Ben Gottlieb's Twitter-OAuth-iPhone class to post status updates in app. I have successfully done so, when executed on the application's main thread. But, when I throw it in a "NSThread detachNewThreadSelector" the post never makes it to twitter. It processes fine and I get a proper [connection identifier], but the results never make it on twitter. Any idea how I can get this to run in a thread without bringing it back to the main thread?
Code added
Tweet method
-(void)tweet{
if([_engine isAuthorized]){
[_engine sendUpdate:#"Tweeting"];
}
}
Doesn't work:
[NSThread detachNewThreadSelector:#selector(tweet) toTarget:self withObject:nil];
Does work (from main app):
[self tweet];
Does work (from within a thread):
[self performSelectorOnMainThread:#selector(tweet) withObject:nil waitUntilDone:NO];

Execute a method that takes a second to complete without temporarily halting code

Basically, i have a method that takes a few seconds to complete as it copies some files using NSFileManager. This is invoked on the touchesMoved event when the user picks up a draggable UIView icon. However, there's a slight delay before the icon's position is updated. I'm guessing it's waiting for that method to copy it's files before continuing. The method HAS to be triggered on touchesMoved, so please don't suggest moving it.
How can i execute a method that takes about a second to complete, without holding up the code?
(..and don't worry the copy method doesn't get repeatedly called from the touchesMoved event)
You could perform the task in the background using performSelectorInBackground:...:
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
This prevent that selector from blocking the main thread.
Example:
[self performSelectorInBackground:#selector(myMethod) withObject:nil];
Do it in a background thread. Leave the main thread to deal with UI stuff only.
Technically you could divide the copying of files into very small chunks, and tell the current NSRunLoop to dispatch between each file copy.
But practically just say no to any IO access on the main thread, all IO access should be done in the background. Even the slightest block on the main thread will make the UI stutter and be unresponsive, Android user might accept that, iOS user do not.
Your options are numerous, and easy to implement. You could do a simple performSelector–:
-(void)backgroundWorker {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Do your stuff
[pool release];
}
-(void)startDoingIOStuff {
[self performSelectorInBackground:#selector(backgroundWorker)
withObject:nil];
}
You could do it practically inline using a block and GCD:
-(void)startDoingIOStuff {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL),
^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Do your stuff
[pool release];
});
}
Or you could use an NSOperation on a NSOperationQueue. I have written a longer blog post on this topic, including source code that is available here: http://blog.jayway.com/2010/08/19/future-cocoa-operation/
Before immediately resorting to a secondary thread, it would certainly be worth a try to use a plain old performSelector on self. For example:
[self peformSelector:#selector(copyFiles) withObject:nil afterDelay:0.0];
Note that this is different from doing:
[self copyFiles];
The peformSelector version basically says "do copyFiles ASAP, OK?", but doesn't block everything while waiting for it to be done. In other words, it's possible that the perform selector version would allow the main event loop to update the UI (thereby preventing the apparent visual lag) before the file copying is actually done.

When NSThread returns to a released object? (iPhone)

I have got a memory bug that seems to boil down to something happening in a thread. I am having difficulties troubleshooting this.
I have a UIViewController, that when active, i.e. the user is using its view, retrieves updates from a web service in an NSThread.
This is done every 3 minutes and this delay is controlled by a:
[self performSelector:#selector(timerDone) withObject:nil afterDelay:180.0];
The timerDone method now starts the NSThread that retrieves the web service data and also it sends the performSelector message again. This is a little "check for updates, populate views, shut everything down, repeat" routine that works just fine.
Now, the user can of course suddenly tap a button an load up a second UIViewController. When this happens I call:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(timerDone) object:nil];
And do my cleaning up in the dealloc method.
My question is now: What happens if the NSThread was running while the user changed the view and set in motion the deconstruction of this object that is the starting point of the NSThread?
Should I keep a BOOL around that tells me if the NSThread is still active, and if so, what to do with the NSThread if this is the case.
The threading is done like this:
- (void) runTimer {
[self performSelector:#selector(timerDone) withObject:nil afterDelay:180];
}
- (void) timerDone {
[self performSelector:#selector(runTimer) withObject:nil afterDelay:2];
[NSThread detachNewThreadSelector:#selector(updateAllVisibleElements) toTarget:self withObject:nil];
}
- (void) updateAllVisibleElements {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//call approiate web service
[pool release];
}
You have two problems here: first, you're using performSelector:withObject:afterDelay: to do what an NSTimer does best (periodic callback). cancelPreviousPerformRequestsWithTarget:selector:object: can be quite expensive, and because of your threading is likely creating race conditions.
Second problem: each thread has its own run loop, and both mechanisms (performSelector:... and NSTimer) and are tied to the current thread's run loop.
Here's what I recommend: Create a single, long-lived NSThread with its own explicit run loop for all your update needs. Look at the Threading Programming Guide for some good example code of this. On that thread, set up a 3-minute repeating NSTimer. Every 3 minutes, update.
If you need to schedule an update outside the three-minute cycle, then you use performSelector:onThread:withObject:waitUntilDone: to call your updateAllVisibileElements. The way I generally do this is to encapsulate all of the thread logic into a single object (WebServiceController or whatever). It creates it own NSThread and saves it in an ivar. Then I use code like this:
- (void)requestUpdate
{
if ([NSThread currentThread] != self.thread)
{
[self performSelector:#selector(update) onThread:self.thread withObject:nil waitUntilDone:NO];
return;
}
else
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//call approiate web service
[pool drain];
}
}
One more note: you mention that the background thread "populates views." A background thread should never call into UIKit. UIKit is not thread safe and should only be called on the main thread. I typically achieve this by posting notifications onto the main thread which the view controllers observe. The "updating" object should not know anything about the UI. That breaks the Model-View-Controller paradigm of Cocoa.