This question already has answers here:
How can I programmatically pause an NSTimer?
(16 answers)
Closed 9 years ago.
I have a game which uses a timer. I want to make it so the user can select a button and it pauses that timer and when they click that button again, it will unpause that timer. I already have code to the timer, just need some help with the pausing the timer and the dual-action button.
Code to timer:
-(void)timerDelay {
mainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
-(void)countDownDuration {
MainInt -= 1;
seconds.text = [NSString stringWithFormat:#"%i", MainInt];
if (MainInt <= 0) {
[timer invalidate];
[self delay];
}
}
That's very easy.
// Declare the following variables
BOOL ispaused;
NSTimer *timer;
int MainInt;
-(void)countUp {
if (ispaused == NO) {
MainInt +=1;
secondField.stringValue = [NSString stringWithFormat:#"%i",MainInt];
}
}
- (IBAction)start1Clicked:(id)sender {
MainInt=0;
timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countUp) userInfo:Nil repeats:YES];
}
- (IBAction)pause1Clicked:(id)sender {
ispaused = YES;
}
- (IBAction)resume1Clicked:(id)sender {
ispaused = NO;
}
There is no pause and resume functionality in NSTimer. You can impliment it like below code.
- (void)startTimer
{
m_pTimerObject = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(fireTimer:) userInfo:nil repeats:YES];
}
- (void)fireTimer:(NSTimer *)inTimer
{
// Timer is fired.
}
- (void)resumeTimer
{
if(m_pTimerObject)
{
[m_pTimerObject invalidate];
m_pTimerObject = nil;
}
m_pTimerObject = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(fireTimer:) userInfo:nil repeats:YES];
}
- (void)pauseTimer
{
[m_pTimerObject invalidate];
m_pTimerObject = nil;
}
Related
I want to show user that the value initially is 0 than it increase to 1 than 2 than 3 sequence repeat after some seconds
Worked done by me
I write this code in viewdidload but it print 99 in label directly but i want to show user changing values from 0 to 99.
for(int i=0;i<100;i++){
_totalEffort.text=[NSString stringWithFormat:#"%d",i];
}
I think this will help you:
#interface ViewController (){
int i;
NSTimer *myTimer;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self
selector:#selector(setData)
userInfo:nil
repeats:YES];
i = 0;
}
-(void)setData{
_totalEffort.text=[NSString stringWithFormat:#"%d",i];
i = i + 1;
if(i == 100){
[myTimer invalidate];
myTimer = nil;
}
}
Based on your requirement you need to use NSTimer for update your label progress
Step 1: Create 2 variable in your #interface class
#interface BUViewController: UIViewController {
NSTimer *timerCount;
int progress;
}
Step 2: Start Timer in your viewDidLoad() with progress value 0.
progress = 0;
timerCount = [NSTimer timerWithTimeInterval:0.5 target:self selector:#selector(updateLabel) userInfo:nil repeats:YES];
Step 3: create method with timer update label text an check progress value in it and stop timer while its reach 100.
-(void)updateLable{
if (progress<100) {
lblProgress.text = [NSString stringWithFormat:#"%d",progress];
progress++;
}else{
[timerCount invalidate];
timerCount = nil;
}
}
Hope this will help you to achieve your expected output.
For this you can use NSTimer you need to update UILabel value in its selector method. You can use this code.
-(void)viewDidLoad{
[super viewDidLoad];
self.time = 0;
_labelTimer.text =#"0";
[self startTimer];
}
- (void)startTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerAction:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
}
- (void)timerAction:(NSTimer *)timer {
self.time++;
if (self.time == 100)
{
[self stopTimer];
}
_labelTimer.text = [NSString stringWithFormat:#"%d",self.time];
}
-(void)stopTimer{
[self.timer invalidate];
self.timer = nil;
}
Here is code for your problem .hope it helps you.
- (void)viewDidLoad
{
[super viewDidLoad];
counter = 0;
t = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(updateLabel) userInfo:nil repeats:YES];
}
-(void)updateLabel
{
for (int i = counter; i<counter+1; i++)
{
_totalEffort.text=[NSString stringWithFormat:#"%d",i];
}
counter++;
if (counter ==101)
{
[t invalidate];
}
}
You are blocking run loop with your cycle. You just need resume it in each iteration.
for(int i=0;i<100;i++){
_totalEffort.text=#(i).stringValue;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
I have a button that when pressed generates random numbers triggered by NSTimer at a certain frequency, and when released I would like it to keep generating them, just more slower and slower until it stops.
- (void)buttonPressed {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:#selector(generateNumber) userInfo:nil repeats:YES];
}
- (void)buttonReleased {
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
for (float i=0.20; i<1; i += 0.1) {
_timer = [NSTimer scheduledTimerWithTimeInterval:i target:self selector:#selector(generateNumber) userInfo:nil repeats:NO];
}
}
It works fine while the button is pressed, but once I release it actually accelerate and then stops all in a sudden. Any idea why it wouldn't be working or any alternative way I can reach the wanted result?
Once your button is released, generation accelerates because at that moment you schedule 8 timers with intervals 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 and 0.9 starting at the time of button release, which means each will execute 0.1s after the other, which is a smaller interval than your original timer (0.2s).
This is an alternative
#interface ViewController ()
#property (nonatomic, retain) NSTimer *timer;
#property (nonatomic) float curInterval;
#end
#implementation ViewController
- (IBAction)buttonDown {
self.curInterval = 0.1;
[self updatePressed];
}
- (void)updatePressed {
[self generateNumber];
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.curInterval target:self selector:#selector(updatePressed) userInfo:nil repeats:NO];
}
- (IBAction)buttonUp {
[self.timer invalidate];
[self updateUp];
}
- (void)updateUp {
[self generateNumber];
self.curInterval += 0.1;
if (self.curInterval < 1.0f) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:self.curInterval target:self selector:#selector(updateUp) userInfo:nil repeats:NO];
}
}
#end
In Button release method you are using for loop which keeps on executing untill it reaches interval of 1. What you need to do is take a global float value and initialize it to 0.20 at start. On button pressed pass that value. On button release increment the global variable and pass that value to NSTimer instead of for loop
float numTimer = 0.20f;
- (void)buttonPressed {
_timer = [NSTimer scheduledTimerWithTimeInterval:numTimer target:self selector:#selector(generateNumber) userInfo:nil repeats:YES];
}
- (void)buttonReleased {
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
numTimer = numTimer + 0.1f;
_timer = [NSTimer scheduledTimerWithTimeInterval:numTimer target:self selector:#selector(reGenerateNumber) userInfo:nil repeats:NO]; }
}
-(void) reGenerateNumber {
[self generateNumber];
if ([_timer isValid]) {
[_timer invalidate];
}
_timer = nil;
numTimer = numTimer + 0.1f;
_timer = [NSTimer scheduledTimerWithTimeInterval:numTimer target:self selector:#selector(reGenerateNumber) userInfo:nil repeats:NO];
}
I develop One Application. In my application, there are Two UIButtons , StartBtn and StopBtn, And also I use NSTimer.
Now, i want to start NSTimer when user click on StartBtn and also stop when your click on StopBtn.
I want to set NSTimer for 1 minute and if i stop timer in 30 sec. then remaining 30 sec. will again start when i click on StartBtn again and after complete 1 minute it should display alertMessage.
I know that NSTimer is stopped by [MyTimerName invalidate]; method but I don't know how to pause it and again starts with last stoped time?
There is no event called pause in NSTimer
To achieve pause and resume function below is what you can do.
When you click start, notice the current time.
When you click pause, notice the current time.
When you click start again, you will create NSTimer with time remaining from Step 2 time - Step 1 time.
Hope you got idea on what needs to be done...
- (IBAction)btn_start:(id)sender
{
if ([startpause.titleLabel.text isEqualToString:#"Start"])
{
[startpause setTitle:#"Pause" forState:UIControlStateNormal];
[startpause setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
if (!_myTimer)
{
_myTimer = [self createTimer];
}
[self.viewww setHidden:NO];
[self.shuffle_out setUserInteractionEnabled:YES];
[self.viewww setUserInteractionEnabled:YES];
}
else if ([startpause.titleLabel.text isEqualToString:#"Pause"])
{
[startpause setTitle:#"Start" forState:UIControlStateNormal];
[startpause setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
if (!_currentTimeInSeconds)
{
_currentTimeInSeconds = 0 ;
}
[_myTimer invalidate];
[self.shuffle_out setUserInteractionEnabled:NO];
[self.viewww setHidden:YES];
[self.viewww setUserInteractionEnabled:NO];
}
}
- (NSTimer *)createTimer
{
return [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerTicked:)
userInfo:nil
repeats:YES];
}
- (NSString *)formattedTime:(int)totalSeconds
{
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
return [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
}
- (void)timerTicked:(NSTimer *)timer
{
_currentTimeInSeconds++;
self.lbl_timer.text = [self formattedTime:_currentTimeInSeconds];
if ([lbl_timer.text isEqualToString:#"01:00"])
{
[_myTimer invalidate];
//lbl_timer.text=#"00:00";
[startpause setTitle:#"Start" forState:UIControlStateNormal];
[startpause setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
UIAlertView *alrt=[[UIAlertView alloc]initWithTitle:nil message:#"⏰...Game Over...⌛️" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alrt show];
}
}
This is working like charm for me...
Create Object Like..
NSTimer *timer;
To Stop Timer
if (timer)
{
[timer invalidate];
timer = nil;
}
To Start Timer
timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(percentageUpdate) userInfo:nil repeats:YES];
other way you can also cancel in viewDidDisappear Method
- (void) viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (timer)
{
[timer invalidate];
timer = nil;
}
}
The only way to invalidate and re create NSTimer object
There is no direct way of doing this. You can materialise this in below fashion:
Step 1 : Create properties to hold your timer, a count timer and a counter to count the time elapsed
#property (nonatomic, assign) NSInteger timerCount;
#property (nonatomic, strong) NSTimer *myCountTimer;
#property (nonatomic, strong) NSTimer *myTimer;
Step 2 : Start your timer, count timer and implement the timer handlers:
- (void)startTimer {
self.myCountTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(countTimer:) userInfo:nil repeats:NO];
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:#selector(fireTimer:) userInfo:nil repeats:NO];
}
- (void)countTimer:(NSTimer *)inTimer {
self.timerCount += 1;
}
- (void)fireTimer:(NSTimer *)inTimer {
// Timer is fired.
}
Step 3 : Implement play/pause timers:
- (void)pauseTimer {
[self.myTimer invalidate];
self.myTimer = nil;
}
- (void)resumeTimer {
if(self.myTimer) {
[self.myTimer invalidate];
self.myTimer = nil;
}
NSInteger remainingTime = 60 - self.timerCount;
self.myTimer = [NSTimer scheduledTimerWithTimeInterval:remainingTime target:self selector:#selector(fireTimer:) userInfo:nil repeats:YES];
}
In Objective-C
Declare two global var as
int time;
NSTimer *timer;
- (IBAction)start:(id)sender
{
timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(increaseTimer) userInfo:nil repeats:YES];
}
- (IBAction)pause:(id)sender
{
[timer invalidate];
}
- (IBAction)reset:(id)sender {
[timer invalidate];
time = 0;
_lbl_tmer.text=#"0";
}
-(void)increaseTimer {
time++;
NSString *str=[NSString stringWithFormat:#"%d",time];
_lbl_tmer.text = str;
}
In Swift
Declare two global var
var timer = NSTimer()
var time = 0
Thenceforth manipulate them accordingly
#IBOutlet var timerLabel: UILabel!
func increaseTimer() {
time++
timerLabel.text = "\(time)"
}
#IBAction func play(sender: AnyObject) {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("increaseTimer"), userInfo: nil, repeats: true)
}
#IBAction func pause(sender: AnyObject) {
timer.invalidate()
}
#IBAction func reset(sender: AnyObject) {
timer.invalidate()
time = 0
timerLabel.text = "0"
}
Happy Coding.. :)
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have a timer in my application.There are buttons to start and stop,one button for pause and resume.
ex-
start- starts from 0sec;
pause- pause at 20sec;
resume- i wait for 10 sec then press resume, timer starts from 30sec;
code for pause timer
(IBAction)pauseTimer:sender
{
[self.timer invalidate];
self.timer = nil;
}
But i want it to start from 21sec how to do that??
Help me please.Thanks in advance
I Hope that you need a Instance Variable(NSInteger) to keep track on it .
For ex:
NSNumber intForKeepTrackOnTime;
- (IBAction)startTimer:(id)sender
{
if (_timer == nil)
{
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(_timerFired)
userInfo:nil
repeats:YES];
}
}
- (IBAction)stopTimer:(id)sender
{ // Invalidate the timer and also nil the Value of Tracking Variable.
intForKeepTrackOnTime = 0;
if (_timer != nil)
{
[_timer invalidate];
_timer = nil;
}
}
- (IBAction)pauseTimer:(id)sender
{ // Invalidate the timer only
if (_timer != nil)
{
[_timer invalidate];
_timer = nil;
}
}
- (IBAction)resumeTimer:(id)sender
{ //Start the timer only.
if (_timer == nil)
{
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(_timerFired)
userInfo:nil
repeats:YES];
}
}
- (void)_timerFired
{ //Keep Track on
intForKeepTrackOnTime++;
}
Here's the basic outline of a class to achieve this. The idea is that the timer fires every second and timer is only accumlated (into _timerValue) if the paused flag (_paused) is NO.
TimerClass.h:
#interface TimerClass : NSObject {
NSTimer *_timer;
BOOL _paused;
NSInteger _timerValue;
}
#end
TimerClass.m:
#implementation TimerClass
- (IBAction)startTimer:(id)sender {
NSAssert(!_timer, #"Already started");
_timerValue = 0;
_paused = NO;
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(tick:)
userInfo:nil
repeats:YES];
}
- (IBAction)stopTimer:(id)sender {
[_timer invalidate];
_timer = nil;
}
- (IBAction)pauseTimer:(id)sender {
_paused = YES;
}
- (IBAction)resumeTimer:(id)sender {
_paused = NO;
}
- (void)tick:(NSTimer *)timer {
if (!_paused)
_timerValue++;
}
#end
I have this app which has a timer in it and I want to be able to display a button at random points in that timer. Sort Of like a game setting where you have to get the button to get more time before it disappears. I already have some code , but the problem is that the timer that i already have is being messed up ( i can tell because it is linked to a label. It messed up because it goes down by 2 instead of 1 and this only happens when i have the code to make the button appear and disappear with the timer.
Here is the code to my timer that is being messed up:
-(IBAction)Ready:(id)sender {
[self performSelector:#selector(TimerDelay) withObject:nil afterDelay:1.0];
[self performSelector:#selector(randomTimer) withObject:nil afterDelay:0.5];
}
-(void)TimerDelay {
MainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
Here is the code to the button:
-(IBAction)Ready:(id)sender { //the same ready action as above
[self performSelector:#selector(TimerDelay) withObject:nil afterDelay:1.0];
[self performSelector:#selector(randomTimer) withObject:nil afterDelay:0.5];
}
-(void)TimerDelay {
MainInt = 36;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(countDownDuration)
userInfo:nil
repeats:YES];
}
- (void)randomTimer {
NSInteger randomTime = arc4random_uniform(0); //Some number between 0 and 9
timer = [NSTimer scheduledTimerWithTimeInterval:randomTime
target:self
selector:#selector(showButton)
userInfo:nil
repeats:NO];
}
- (void)showButton {
if(self.plus5.hidden == YES) {
self.plus5.hidden = NO;
}
else {
self.plus5.hidden = YES;
}
[self TimerDelay]; //Call random timer function again to run this method at a future random time
}
You are calling "randomTimer" and "TimerDelay" (this should be "timerDelay") one after the other and scheduling and REscheduling "timer".
I think you should reconsider your architecture, here...
EDIT: Use just one timer and let it manage your button.
- (void)somewhereInYourCode
{
shouldShowButton = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timeFired)
userInfo:nil
repeats:YES];
}
- (void)timeFired
{
// Here your countdown and...
if (shouldShowButton) {
NSInteger randomTimeInt = arc4random_uniform(9); // as suggested by Bergasms
float randomTimeFloat = randomTimeInt;
[self performSelector:#selector(showButton) withObject:nil afterDelay:randomTimeFloat];
shouldShowButton = NO;
}
}
This way your timer won't (probably) mess up.
This:
arc4random_uniform() will return a uniformly distributed random number
less than upper_bound.
is one of your problems.
NSInteger randomTime = arc4random_uniform(0); //Some number between 0 and 9
needs to be
NSInteger randomTime = arc4random_uniform(9); //Some number between 0 and 9
I cannot say for the rest of your code. But the line you have will always return 0, which means the random timer will always execute instantly.