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.. :)
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 chatting app that has a uiswitch. If the Switch button is on, I want the app to send "hi" continuously every 3 seconds even the app is in background mode. I know that I can use NSTimer, but I don't really know how to implement that in this code(This is my first time to develop iOS app). Please help me with this.
My code is :
// Allocate, initialize, and add the automatic button.
_AutomaticSend = [[UISwitch alloc] initWithFrame:CGRectMake([self width] - 50.0, textAreaY + Center(160.0, textAreaHeight), 50.0, 50.0)];
[_AutomaticSend addTarget:self action:#selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
and
// Switch action
//NSUInteger counter = 0;
- (void)changeSwitch:(id)sender{
if([sender isOn]){
for (int a=1; a<=300; a++)
{
//[self performSelector:#selector(changeSwitch:) withObject:_textField afterDelay:70.0];
[sender setOn:YES animated:YES];
[_textField setText:#"hi"];
NSString * text = [_textField text];
// Update status.
[[TSNAppContext singleton] updateStatus:text];
// Add the status to the bubble.
[self appendLocalPeerTableViewCellWithMessage:text];
}
// NSLog(#"Switch is ON");
} else{
NSLog(#"Switch is OFF");
}
}
Now, the app is showing all "hi" after all 300 "hi" is ready to show. But I want it to send it one by one continuously.
Define a NSTimer instance and a counter in your view controller:
#property (nonatomic, strong) NSTimer *timer;
#property (nonatomic, assign) NSInteger counter;
Implement the method when timer is fired:
- (void)timerAction:(id)sender {
[_textField setText:#"hi"];
NSString * text = [_textField text];
// Update status.
[[TSNAppContext singleton] updateStatus:text];
// Add the status to the bubble.
[self appendLocalPeerTableViewCellWithMessage:text];
// stop the timer after sending for 300 times
self.counter += 1;
if (self.counter >= 300) {
[self.timer invalidate];
self.timer = nil;
}
}
Starts the timer when switch is on:
- (void)changeSwitch:(id)sender{
if ([sender isOn]) {
self.counter = 0;
self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:#selector(timerAction:) userInfo:nil repeats:YES];
} else {
// kill the timer when switch is off
[self.timer invalidate];
self.timer = nil;
}
}
However, you can't make the timer to continue working indefinitely after your app is entering background (with some exceptions: VoIP, GPS applications, etc.). Please refer to the official document Background Execution.
//Nstimer *timer in .h
In your UISwitch Method Write like this
- (void)changeSwitch:(id)sender{
if([sender isOn]){
timer=[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod)
userInfo:nil
repeats:NO];
}
else
{
[timer invalidate];
}
}
targetMethod Like this
-(void)targetMethod
{
[sender setOn:YES animated:YES];
[_textField setText:#"hi"];
NSString * text = [_textField text];
// Update status.
[[TSNAppContext singleton] updateStatus:text];
// Add the status to the bubble.
[self appendLocalPeerTableViewCellWithMessage:text];
}
Use NSTimer: Documentation of NSTimer
Declare property of NSTimer in .h file:
#property (retain,nonatomic) NSTimer *myTimer;
- (void)changeSwitch:(id)sender
{
if([sender isOn]){
myTimer = [NSTimer scheduledTimerWithTimeInterval: 4 target: self
selector: #selector(AddMessage:) userInfo: nil repeats: YES];
} else{
[self.timer invalidate];
}
}
After each 4 second, timer will call the below function:
-(void) AddMessage:(NSTimer*) timer
{
//Add Message
}
Sorry this is a repeat question, but I have tried all the solutions I could find without success.
Anyway, here is my problem, specifically. I have the following code where I start a timer on a long press gesture, then stop it when that gesture is cancelled or when the action is complete.
-(void)photoLongPress:(UILongPressGestureRecognizer *)press
{
NSTimer *timer = nil;
if (press.state == UIGestureRecognizerStateBegan)
{
//Start timer
timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(photoLongPressTimer:) userInfo:nil repeats:YES];
}
if (press.state == UIGestureRecognizerStateEnded)
{
[timer invalidate];
timer = nil;
}
}
-(void)photoLongPressTimer:(NSTimer *)timer
{
DAProgressOverlayView *progress = (DAProgressOverlayView *)[self.view viewWithTag:kTagPhotoDeleteProgressIndicator];
progress.progress += 0.08;
if (progress.progress == 1)
{
[self deletePhotoSelection];
[timer invalidate];
timer = nil;
}
}
The timer stops when invalidated in the photoLongPressTimer method, but not if the gesture stops in the photoLongPress method. Why might this be? I'm stumped.
Thanks.
You need to store timer in an instance variable so that you can refer to it later. It works in photoLongPressTimer: because the timer is passed as a parameter but in photoLongPress: it is nil because you haven't just created it and it's a local reference.
Add a property:
#property (strong, nonatomic) NSTimer *timer;
Store the new timer into it:
self.timer = [NSTimer schedu...
Invalidate and nil the property:
[self.timer invalidate];
self.timer = nil;
NSTimer *timer = nil;
This line only creates a local variable.
You must make a property for the timer.
Put this in your .h file.
#property (strong) NSTimer *timer;
Then use the code here
-(void)photoLongPress:(UILongPressGestureRecognizer *)press
{
if (press.state == UIGestureRecognizerStateBegan)
{
//Start timer
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(photoLongPressTimer:) userInfo:nil repeats:YES];
}
if (press.state == UIGestureRecognizerStateEnded)
{
[self.timer invalidate];
self.timer = nil;
}
}
-(void)photoLongPressTimer:(NSTimer *)timer
{
DAProgressOverlayView *progress = (DAProgressOverlayView *)[self.view viewWithTag:kTagPhotoDeleteProgressIndicator];
progress.progress += 0.08;
if (progress.progress == 1)
{
[self deletePhotoSelection];
[timer invalidate];
timer = nil;
}
}
Problem is with NSTimer *timer = nil;
in -(void)photoLongPress:(UILongPressGestureRecognizer *)press
method.
remove NSTimer *timer = nil; from this method and store instance of NSTimer.
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;
}
I made a stopwatch application recently and it had a few glitches.
If I hit the stop button twice in a row, the entire app would crash.
If I hit the start button twice in a row, the timer would run twice as fast and the stop button would stop working.
How do I fix this problem?
Here is the code in my .h file:
IBOutlet UILabel *time;
IBOutlet UILabel *time1;
IBOutlet UILabel *time2;
NSTimer *myTicker;
NSTimer *myTicker2;
NSTimer *myTicker3;
}
- (IBAction)start;
- (IBAction)stop;
- (IBAction)reset;
- (void)showActivity;
- (void)showActivity1;
- (void)showActivity2;
#end
and here is my code in the .m file:
- (IBAction)start {
myTicker = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
myTicker2 = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:#selector(showActivity1) userInfo:nil repeats:YES];
myTicker3 = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(showActivity2) userInfo:nil repeats:YES];
}
- (IBAction)stop {
[myTicker invalidate];
[myTicker2 invalidate];
[myTicker3 invalidate];
}
- (IBAction)reset {
time.text = #"00";
time1.text = #"00";
time2.text = #"00";
}
- (void)showActivity {
int currentTime = [time.text intValue];
int newTime = currentTime + 1;
if (newTime == 60) {
newTime = 0;
}
time.text = [NSString stringWithFormat:#"%d", newTime];
}
- (void)showActivity1 {
int currentTime1 = [time1.text intValue];
int newTime1 = currentTime1 + 1;
if (newTime1 == 10) {
newTime1 = 0;
}
time1.text = [NSString stringWithFormat:#"%d", newTime1];
}
- (void)showActivity2 {
int currentTime2 = [time2.text intValue];
int newTime2 = currentTime2 + 1;
time2.text = [NSString stringWithFormat:#"%d", newTime2];
}
Set the stop button's userInterActionEnabled property to NO and the start button's to YES when the -stop method is fired. Then switch and set the stop button's userInterActionEnabled to YES and the start button's to NO when -start is fired.
You should create a private BOOL variable "isRunning", which is checked when clicked on Stop or Start like:
- (IBAction)stop {
if(!isRunning) return;
[myTicker invalidate];
[myTicker2 invalidate];
[myTicker3 invalidate];
self.isRunning = NO;
}
etc. Also ignoring user interactions is general a good idea (like CodaFi suggested), but only fights the symptoms ;-) You really should do both checks.