I have a timer that launches in viewDidLoad that looks like this
[NSTimer scheduledTimerWithTimeInterval:0.001f target:self selector:#selector(Dragon:) userInfo:nil repeats:YES];
I want to be able to change my Interval with a variable. However, any time I try to place a variable where the 0.001f is I get errors... any ideas?
I have an app that does exactly what you are asking. I allow the user to change the speed of the timer within the app so I need to make that speed a variable. Here's how I did it:
I create a timer property on my main view controller class.
I initialize the timer when the main view controller class loads.
Each time thereafter, I invalidate my timer and reset it when the value changes.
Some snippets from inside of my main view controller .m file:
//How often to switch views (float)
#define kInterval [[NSUserDefaults standardUserDefaults] integerForKey:#"interval"]
- (void) viewDidAppear:(BOOL)animated{
[self setTimer];
}
- (void) setTimer{
[self.timer invalidate];
[self setTimer: [NSTimer scheduledTimerWithTimeInterval:kInterval target:self selector:#selector(timerFired) userInfo:nil repeats:YES]];
}
Is the app returning from a background process? If so, you may need to re-set the timer. You might also want to peek at CADisplayLink: http://developer.apple.com/library/ios/#documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html%23//apple_ref/doc/uid/TP40009031
#King Popsicle you can take help of this method
(void)applicationWillEnterForeground:(UIApplication *)application OR
(void)applicationDidBecomeActive:(UIApplication *)application
You can fix the things in this method regarding the timer values :)
Related
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.
How to switch from view1 to view 2 without having any button pressed. In my views i have is uiimageview and uitextview
With the NSTimer i m trying to do this
in the viewdidload method by using the following code:
In the firstviewcontroller.h file
#interface FirstViewController : UIViewController
{
NSTimer *SwitchingTimer;
}
In the firstviewcontroller.m file
- (void)viewDidLoad
{
[super viewDidLoad];
SwitchingTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(SwitchView) userInfo:nil repeats:YES];
}
-(void)SwitchViews:(id)sender
In the secondviewcontroller.m file
-(void) SwitchView
{
SecondViewController *SecondView = [[SecondViewController alloc]
initWithNibName:#"SecondViewController" bundle:nil];
SecondView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:SecondView animated:YES];
[SwitchingTimer invalidate];
self.SwitchingTimer = nil;
}
but nothing is happening. Can someone please tell me what i m missing in my code. Will appreciate help.
Thanks in advance.
There are a few issues in your code that are worth mentioning though I am not sure if those will provide you a solution.
Why do you want to repeat the timer every 2 seconds. I think you just want to switch to next view only once and if so then dont repeat the timer. So no need to invalidate the timer.
Your code for the SwitchView method is leaking memory. Please make sure that the SecondView is released after presenting the modal view(in case you are not using ARC).
Please follow the standard naming conventions. For eg: methods and variables should start with lowercase.
Regarding your issue please make sure that the nib name is correct and you are getting a valid object for the second view controller. You can check by using NSLog. Also ensure that the method Switchview is called. Try putting a break point and verify that it is called.
Another Option
If you just want to switch the view only once you can go for another option which does not make use of the NSTimer. For this, you can use performSelector:withObject:afterDelay:. This is just another option for the scenario I mentioned above.
You need to add it to the run loop:
- (void)viewDidLoad
{
[super viewDidLoad];
SwitchingTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(SwitchView) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer: SwitchingTimer forMode:NSDefaultRunLoopMode];
}
Also, you could rename -(void)SwitchView to -(void)switchViewTimerDidFire:(NSTimer *)timer. From the Documentation:
[...] The selector must have the following signature:
- (void)timerFireMethod:(NSTimer*)theTimer
The timer passes itself as the argument to this method.
I have created a NSTimer in my application which gets fired after every 1 min interval. my problem is when I put the application in background and after some time say 5 min, i bring that in foreground, the timer object gets zombied.
any thoughts on this.
Perhaps invalidate the timer when the application enters the background then start it again when the application enters the foreground.
Like so:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[myTimer invalidate];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
myTimer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:#selector(TimerFunction) userInfo:nil repeats:YES];
}
NSTimer objects are retained when scheduled. Your timer might be invalidated for some reason and by thus, released.
I'm trying to invalidate a timer when my app goes into background. The timer gets invoked when you hit a button that starts the timer and is in the TimerController.m file. Here is how it gets invoked.
mytimer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(updateTime) userInfo:nil repeats:YES];//Timer with interval of one second
[[NSRunLoop mainRunLoop] addTimer:mytimer forMode:NSDefaultRunLoopMode];
Now, I'd like to invalidate mytimer when the app goes into background, so I tried putting
[mytimer invalidate];
into the - (void)applicationDidEnterBackground:(UIApplication *)application method the apps delegate. But this won't work since it's undeclared in the delegate. I thought by including TimerController.h into the delegate, this would work, but it won't.
So, I clearly don't know what I'm doing here. Can you help? How do it get it so that mytimer is invalidated when the app goes into background?
There’s also a UIApplicationDidEnterBackgroundNotification notification posted when the application goes into background. You can subscribe for this notification in your controller and handle the transition there:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(goBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
// and later:
- (void) goBackground {
[timer invalidate], timer = nil;
}
if (timer) {
[timer invalidate];
timer = nil;
}
in applicationReEnteredForeground notification method will also work
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.