NSTimer Failing to Stop? - ios

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.

Related

iOS UISwitch keep sending message every 4 second

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
}

iOS How to start and pause timer

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.. :)

how to fire timer when create the timer inside block function?

#interface Taxi_MainViewController : Taxi_BaseNavViewController
{
__block NSTimer *timer_;
}
[Taxi_do_order psg_place_orderWithMemberId:strMemberId_ orderStatus:K_orderStatus_open andCLLocationCoord:location.coordinate callback:^(NSInteger iOrderId){
[Taxi_StatusView dismiss];
if (iOrderId >=0)
{
isOrderExist = YES;
[weakSelf_ showWaittingDriverAcceptView];
timer_ = [NSTimer scheduledTimerWithTimeInterval:2.0
target:weakSelf_
selector:#selector(actListen:)
userInfo:nil
repeats:YES];
}else
[weakSelf_ hideWaittingDriverAcceptView];
}faile:^(){
[Taxi_StatusView showLostNetWork];
}];
when i call [timer_ invalidate],timer_ = nil; at other method, the timer function still call every 2 second.
In your case, the variable timer_ is never keep, and you lose the pointer
at the end block scope. With a property you have retain / release mechanism.
Try this :
#interface Taxi_MainViewController : Taxi_BaseNavViewController
{
}
#property (nonatomic,retain) NSTimer* timer;
#end
[Taxi_do_order psg_place_orderWithMemberId:strMemberId_ orderStatus:K_orderStatus_open andCLLocationCoord:location.coordinate callback:^(NSInteger iOrderId){
[Taxi_StatusView dismiss];
if (iOrderId >=0)
{
isOrderExist = YES;
[weakSelf_ showWaittingDriverAcceptView];
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:weakSelf_
selector:#selector(actListen:)
userInfo:nil
repeats:YES];
}else
[weakSelf_ hideWaittingDriverAcceptView];
}faile:^(){
[Taxi_StatusView showLostNetWork];
}];

How to pause a NSTimer? [duplicate]

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;
}

NSTimer responding to a uibutton

So, Here is the problem. I am trying to make a timer for my game however it doesnt seem to run.
I started by making a property for nstimer:
#property (nonatomic) NSTimer gameTimer;
and synthesizing it:
#synthesize gameTimer = _gameTimer;
then I use this method to set it:
-(NSTimer *) gameTimer{
if (_gameTimer == nil) _gameTimer = [[NSTimer alloc]init];
return _gameTimer;
}
however when i try to start the timer through a uibutton:
- (IBAction)play:(UIButton *)sender {
_levelNumber = 1;
_en1v = -1;
_en2v = 1;
_en3v = -1;
[self setPath];
_gameTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:#selector(onTimer:) userInfo:nil repeats:YES];
self.play.hidden = TRUE;
}
it doesn't work.
I put an nslog into the onTimer: method and found out that the timer just isn't firing some how?
Am I making an obvious mistake?
You have not started the timer at all.
Use:
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(onTimer:) userInfo:nil repeats:YES];
And while stopping, (may be in stop: method)
[_gameTimer invalidate];
_gameTimer = nil;

Resources