Background repeated job - iphone

I have a question about multithreading in xcode. I have searched for numerous web sites but still cannot get my app to work. I want to do a repeated job every 5sec even the Home button is pressed i.e. continue to time in background. The following is my code:
- (void)viewDidLoad {
[super viewDidLoad];
[NSThread detachNewThreadSelector:#selector(test) toTarget:self withObject:nil];
}
In test.m,
-(void)test {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(sayYeah) userInfo:nil repeats:YES];
[pool release];
}
in sayYeah.m,
-(void)sayYeah {
NSLog(#"yeah");
}
What I expect is "yeah" will continue to pop up every 5sec even the home button is pressed. But it didnt, can anyone have an idea how the multithread should be implemented? Thanks!

You can't unless your app fall is the category VOIP, audio playback or location update.
And you can't use timers.

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.

NSTimer in Objective C when Click on Home Button

I have NSTimer in ViewController Class.. And all the methods for NStimer are in that class.. My NSTimer is working properly for play and pause... When i press home button on iPhone also the timer is working properly(it starts running from the time where the application enters into background when the application enters into foreground)... In my application i am rising an alert quickly when my application enters into foreground(UIAlertview in application didEnterForeGround). Here my NSTimer is running when the alert is on the screen(didn't give response to alert).. I want stop the NSTimer Upto the User responding to my alert... After that I want to start the NSTimer... How Can i do that...? Please help me... Thanks in Advance... I want call the NSTimer methods from Appdelegate.m file... Iam calling these methods properly... And the methods in ViewController are called.. But the action is Not Performing... For the Same method when call from viewController class it is working...
enter code here
ViewController.h
+(ExamViewController *)evcInstance;
ViewController.m
ExamViewController *evc = nil;
#implementation ExamViewController
+(ExamViewController *)evcInstance
{
if(!evc)
{
evc = [[ExamViewController alloc] init];
}
return evc;
}
- (void)onStartPressed
{
stopwatchtimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimer:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:stopwatchtimer forMode:NSRunLoopCommonModes];
resume.hidden = YES;
resume.enabled=NO;
pause.hidden = NO;
pause.enabled=YES;
}
- (void)onStopPressed
{
[stopwatchtimer invalidate];
stopwatchtimer = nil;
pause.hidden = YES;
pause.enabled=NO;
resume.hidden = NO;
resume.enabled=YES;
}
Appdelegate.m
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[[ExamViewController evcInstance] onStopPressed];
NSLog(#"applicationWillEnterForeground");
if(viewCalled ==YES)
{
UIAlertView *alertview=[[UIAlertView alloc]initWithTitle:#"" message:#"DO! You Want To continue" delegate:self cancelButtonTitle:#"YES" otherButtonTitles:#"NO", nil];
[alertview show];
[alertview release];
}
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
a few things:
1) It looks like an incomplete singleton design. If you really want a singleton, refer to a post like this one.
2) No need to add stopwatchtimer to the current run loop. The scheduledTimerWithTimeInterval method schedules it for you.
3) I don't see where you declare stopwatch timer, but be sure to declare it as a retained property (or strong in ARC).
4) To stop the timer, just call [stopwatchtimer invalidate]; To restart it, re-instantiate and overwrite the old one using the same scheduledTimerWithTimeInterval class method that you called originally.
5) To do anything when an alert view completes, implement the delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
So you can invalidate the timer before presenting the alert, then rebuild it when you get notified the alert is finished.

NSTimer scheduledTimerWithTimeInterval: repeats:NO selector method calls multiple times

I am using NSThread along with NSTimer.
My code is like this
-(void) checkForRecentAlarm
{
if ([self.alarmThread isFinished])
{
[self.alarmThread cancel];
}
self.alarmThread = [[NSThread alloc] initWithTarget:self selector:#selector(startTimerForRecentAlarm) object:nil];
[self.alarmThread start];
//[NSThread detachNewThreadSelector:#selector(startTimerForRecentAlarm) toTarget:self withObject:nil];
}
-(void)startTimerForRecentAlarm
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
self.recentAlarmTime = [NSDate date];
self.dbObject = [[RADataBaseModelManager alloc] init];
self.recentAlarmTime = [self.dbObject getMostRecentAlarmTimeFromDB];
if (self.recentAlarmTime) {
NSTimeInterval timeIntervalToAlarm = [self.recentAlarmTime timeIntervalSinceNow];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
//Fire timer every second to updated countdown and date/time
self.RATimer = [NSTimer scheduledTimerWithTimeInterval:timeIntervalToAlarm target:self selector:#selector(timerFireMethod:) userInfo:nil repeats:NO];
[runLoop run];
}
[pool release];
}
- (void)timerFireMethod:(NSTimer*)theTimer
{
[self.RATimer invalidate];
[theTimer invalidate];
self.RATimer = NULL;
theTimer = NULL;
[self playAlarm];
UIAlertView *alarmAlert = [[UIAlertView alloc] initWithTitle:#"Alarm" message:#"" delegate:self cancelButtonTitle:#"Close" otherButtonTitles:#"Snooze", nil];
[alarmAlert show];
[alarmAlert release];
alarmAlert = nil;
}
Now the problem is, my alertbox comes twice for one call in the
startTimerForRecentAlarm
method. So that the alert comes consequently twice and my view get stuck.
What will be problem here?
I am trying to implement an alarm with multiple alarm option using a single NSTimer.
Please help.
When I debug this, I can find many simultaneous threads are running on same code(UIAlertView).
I can't see any obvious reason why that would be called twice, but it does seem like an overly complex way of doing what you need to do.
Have you thought about using local notifications?
If you don't want to do that, you could refactor your code so it works like this:
1. Add a new event
2. If there's no timer or the time to the event is shorter than the time on the timer, then set the timer for this event.
3. When a timer fires, check for the next event and set a timer for that event (if there is one).
This does seem really complex. My general observation is that if you get two timer firings it's because you have two timers for some reason.
If you have multiple threads doing UIAlertView, you have another problem, because you can only (reliably) do UI from the main thread.

Problem in Background Thread in iPhone

I am using Background Thread to update one of my label
I am using the following code. But in iOS 4.0 i have learn that application saves its states and goes to background. and my application also did that work but the thread i am using stops working when i hide the application and again resumes from where i left when i reopen it. Can anybody please tell me what do I need to change in code in order to make the thread keep on running in background and change my GUI while my application is hidden. I am using this code..
-(void)startThread
{
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:#selector(setUpTimerThread) object:nil];
[thread start];
}
-(void)setUpTimerThread
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSTimer *timer = [NSTimer timerWithTimeInterval:3 target:self selector:#selector(triggerTimer) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSRunLoopCommonModes];
[runLoop run];
[pool release];
}
-(void)triggerTimer
{
NSLog(#"***Timer Called after 3 seconds*** %d",count);
self.label.text = [NSString stringWithFormat:#"count value = %d",count];
//self.titleLabel.text= [NSString stringWithFormat:#"count value = %d",count];
count = count +1;
}
Thanks
Timers won't work on relaunch of the application. What you need to do is reinitialize the timer from your appDelegate's applicationDidBecomeActive: method and make sure you shut down the timer from applicationWillEnterBackground: method

Improper behavior of NSTimer on separate thread

I am trying to schedule NSTimer on a separate thread and this is how i am doing it.
-(void) startSpinner {
#ifdef DEBUG_MODE
NSLog(#"Starting Spinner...");
#endif
self.spinnerThread = [[[NSThread alloc] initWithTarget:self selector:#selector(scheduleSpinner) object:nil] autorelease];
[spinnerThread start];
}
-(void) scheduleSpinner {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSTimer *_spinTimer = [NSTimer scheduledTimerWithTimeInterval:SPIN_FIRE_INTERVAL target:self selector:#selector(timerFireMethod:) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:_spinTimer forMode:NSRunLoopCommonModes];
[runLoop addTimer:_spinTimer forMode:UITrackingRunLoopMode];
[runLoop run];
[pool release];
}
timerFireMethod spins my spinner and when a button is pressed (stop button), i invalidate the timer and exit the thread in this method. I do a polling here if spin button is pressed.
The problem is, my timerFireMethod gets called properly for the first time. Spinner spins for first time. But when i stop my spinner and start it again, spinner doesn't spins. The logs say that second time my "startSpinner" method gets called but "timerFireMethod" method is not called.
The worse is, the spinner works 5-6 times on simulator, 1 times on 2g device, 4-5 times on latest ipod. Its random.
How does this basically work? What could be the problem?
Make your NSTimer instance variable a class variable. When you invalidate it, set it to nil immediately afterwards.