How to call NSThread repeatedly? - iphone

I am working on an application where i have to call a thread repeatedly. In that thread we have to parse an XML and i have to get updated data from that xml. now please guide me how to call that thread repeatedly? if my thread is in working and my code calls it again, then i think it will have a crash on it.

Separate the code into a new method
-(void) thisMethodWillRunAsASeparateThread
{
//Threads need their own pool.
NSAutoreleasePool *pool = [NSAutoreleasePool new];
while (thisThreadShouldRun)
{
// run xml parsing code
}
[pool release];
}
and to start the thread:
[NSThread detachNewThreadSelector:#selector(thisMethodWillRunAsASeparateThread) toTarget:self withObject:nil];

To call any code repeatedly you must NSTimer like:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.10f target:self
selector:#selector(methodName) userInfo:nil repeats:YES];
you should to invalidate the timer after use. while if you wan to execute the code using background thread you must this code but this will not repeat multiple times.
[NSThread detachNewThreadSelector:#selector(methodName:) toTarget:self withObject:objName,nil]];

Related

Updating UIView after some time interval?

I want to create Custom Views that call webservice after some time and update themself..The data should be updated even when the application is not in active state.. so What is the best way for doing this ??
Use NSTimer, but data will not update when application is in background mode. After application became active NSTimer will continue working.
you can use NSTimer for that. Add your code in your custom method and call that method like bellow..
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:#selector(yourMethodName:) userInfo:nil repeats:YES];
Here in scheduledTimerWithTimeInterval Parameter you can set the time in seconds so your method which passes in selector Parameter is called after every 3 seconds..
See one Example and tutorial of NSTimer From this link nstimer-tutorial-creating-clockstopwatchtimer-iphoneipad
UPDATE:
If you want to call webservice then you can use NSThread like bellow...
- (void) runTimer
{
[NSThread detachNewThreadSelector:#selector(updateAllVisibleElements)toTarget:self withObject:nil];
}
- (void) updateAllVisibleElements {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if(service == nil)
{
service = [[WebService alloc] init];
}
[service getlocationID:currentLatitude andlongitude:currentLongitute];
[pool release];
}
See the link Here
You'll be able to track the location, but you'll not be able to connect to your web-services when the app is in the background.

How to cancel or stop NSThread?

I'm doing an app that loads the contents of viewControllers using NSThread while is reading an XML file.
I have it done as follows:
-(void)viewDidAppear:(BOOL)animated
{
// Some code...
[NSThread detachNewThreadSelector:#selector(loadXML) toTarget:self withObject:nil];
[super viewDidAppear:YES];
}
-(void)loadXML{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Read XML, create objects...
[pool release];
}
My problem is that I don't know how to stop the NSThread if the user changes to another viewController while the NSThread is loading, doing that the app crashes.
I've tried to cancel or exit the NSThread as follows but without success:
-(void)viewsDidDisappear:(BOOL)animated{
[NSThread cancel];
// or [NSThread exit];
[super viewDidDisappear:YES];
}
Can anyone help? Thanks.
When you detach new thread, you can no more cancel or exit it from viewDidDisappear etc. These UI specific methods execute only on main thread so the exit/cancel applies to the main thread which is obviously wrong.
Instead of using the detach new thread method, declare NSThread variable in .h and initialize it using initWithTarget: selector: object: method and cancel it whenever/wherever you want to..
you can also use [NSThread exit]; method of NSThread.
It's better to let a thread end gracefully, i.e. reach its natural conclusion, if you can. It sounds like in your case you can afford to. Also be sure that you're updating the user interface from the main thread, not a secondary thread, as UIKit is not thread safe.
You wrote:
... the app stops responding while the thread finishes...
Once you flag a thread for cancelling or exit, you have to manually stop whatever the thread was called to do. An example:
....
- (void) doCalculation{
/* Do your calculation here */
}
- (void) calculationThreadEntry{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSUInteger counter = 0;
while ([[NSThread currentThread] isCancelled] == NO){
[self doCalculation];
counter++;
if (counter >= 1000){ break;
} }
[pool release]; }
application:(UIApplication *)application
- (BOOL)
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
/* Start the thread */
[NSThread detachNewThreadSelector:#selector(calculationThreadEntry)
toTarget:self withObject:nil];
// Override point for customization after application launch. [self.window makeKeyAndVisible];
return YES;
}
In this example, the loop is conditioned on the thread being in a non-cancelled state.

iphone: performSelector: withObject: afterDelay: does not work with a background thread?

I want to run a method in a background thread, the first method will run another method on the same (background) thread after some seconds. I wrote this:
- (IBAction)lauch:(id)sender
{
[self performSelectorInBackground:#selector(first) withObject:nil];
}
-(void) second {
printf("second\n");
}
-(void) first {
NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];
printf("first\n");
[self performSelector:#selector(second) withObject:nil afterDelay:3];
printf("ok\n");
[apool release];
}
but the second method is never called, why? and, how may i accomplish my goal?
thanks
You have to have a running run loop for performSelector:withObject:afterDelay: to work.
Your code executes first and, when first exits, the thread is gone. You need to run a run loop.
Add:
[[NSRunLoop currentRunLoop] run];
To the end of first.

NSTimer as a timeout mechanism

I'm pretty sure this is really simple, and I'm just missing something obvious. I have an app that needs to download data from a web service for display in a UITableView, and I want to display a UIAlertView if the operation takes more than X seconds to complete. So this is what I've got (simplified for brevity):
MyViewController.h
#interface MyViewController : UIViewController
<UITableViewDelegate, UITableViewDataSource> {
NSTimer *timer;
}
#property (nonatomic, retain) NSTimer *timer;
MyViewController.m
#implementation MyViewController
#synthesize timer;
- (void)viewDidLoad {
timer = [NSTimer scheduledTimerWithTimeInterval:20
target:self
selector:#selector(initializationTimedOut:)
userInfo:nil
repeats:NO];
[self doSomethingThatTakesALongTime];
[timer invalidate];
}
- (void)doSomethingThatTakesALongTime {
sleep(30); // for testing only
// web service calls etc. go here
}
- (void)initializationTimedOut:(NSTimer *)theTimer {
// show the alert view
}
My problem is that I'm expecting the [self doSomethingThatTakesALongTime] call to block while the timer keeps counting, and I'm thinking that if it finishes before the timer is done counting down, it will return control of the thread to viewDidLoad where [timer invalidate] will proceed to cancel the timer. Obviously my understanding of how timers/threads work is flawed here because the way the code is written, the timer never goes off. However, if I remove the [timer invalidate], it does.
I think there is a problem with scheduling a timer and doing a blocking call on the same thread. Until the blocking call is completed, the run-loop cannot fire the timer.
I suggest you to detach a thread to perform the long operation. Once the long operation is finished, call back on the main thread to invalidate the timer.
Note: it is important to invalidate the timer on the same thread it was scheduled.
- (void)viewDidLoad {
timer = [NSTimer scheduledTimerWithTimeInterval:20
target:self
selector:#selector(initializationTimedOut:)
userInfo:nil
repeats:NO];
[NSThread detachNewThreadSelector:#selector(doSomethingThatTakesALongTime:) toTarget:self withObject:nil];
}
- (void)doSomethingThatTakesALongTime:(id)arg {
sleep(30); // for testing only
// web service calls etc. go here
[self performSelectorOnMainThread:#selector(invalidate) withObject:nil waitUntilDone:NO];
}
- (void)invalidate {
[timer invalidate];
}
- (void)initializationTimedOut:(NSTimer *)theTimer {
// show the alert view
}
Have you tried to use [NSThread sleepforTimeInterval:30]; ?
The sleep() occurs on the main thread and the associated run loop never has the chance to invoke the selector for the timer.
If you would do real work in -doSomething that doesn't block the thread, e.g. non-blocking calls to web-services, it would work as expected. Blocking calls however would have to be done in a different thread so the main run loop does not get blocked.

iPhone-SDK:Call a function in the background?

Is it possible to call my function in the background after certain interval programmatically in iPhone SDK development? I want to call one particular function in the background for certain time intervals(may be every 10 mins) during my app in on running..
Could you please share your ideas.
thanks.
Clave/
Easiest way is to schedule a NSTimer on the main threads run-loop. I suggest that the following code is implemented on your application delegate, and that you call setupTimer from applicationDidFinishLaunching:.
-(void)setupTimer;
{
NSTimer* timer = [NSTimer timerWithTimeInterval:10 * 60
target:self
selector:#selector(triggerTimer:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
-(void)triggerTimer:(NSTimer*)timer;
{
// Do your stuff
}
If your stuff here takes a long time, and you can not hold up the main thread then either call your stuff using:
[self performSelectorInBackground:#selector(myStuff) withObject:nil];
Or you could run the NSTimer on a background thread by with something like this (I am intentionally leaking the thread object):
-(void)startTimerThread;
{
NSThread* thread = [[NSThread alloc] initWithTarget:self
selector:#selector(setupTimerThread)
withObject:nil];
[thread start];
}
-(void)setupTimerThread;
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSTimer* timer = [NSTimer timerWithTimeInterval:10 * 60
target:self
selector:#selector(triggerTimer:)
userInfo:nil
repeats:YES];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forModes:NSRunLoopCommonModes];
[runLoop run];
[pool release];
}
-(void)triggerTimer:(NSTimer*)timer;
{
// Do your stuff
}
You can have a timer, look into NSTimer for that that will fire off every 10 minutes, in order to make i t happen i n the background you have a few options ill name two.
First of note that any UI work should not be done in another thread since UIKit is not thread safe.
You can subclass NSThread and use it to do you process in the background
You can use NSObjects performSelectorInBackground method which basically creates a thread and executes the method. Heres a reference http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelectorInBackground:withObject:
NSThread reference here http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSThread_Class/Reference/Reference.html
NSTimer reference here
http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/Reference/NSTimer.html
To call the function on the main thread, use an NSTimer.
To call it on another thread, create an NSOperation and set up an NSOperationQueue to call it.