Pause and resume Timer in ViewController - objective-c

I want to pause and resume timer in viewcontroller which is displayed as subview in mainviewcontroller. Play/Pause button in mainviewcontroller when pressed it displays view controller as subview as well as plays audio.
Have this NSTimer in view controller
[NSTimer scheduledTimerWithTimeInterval:2.6
target:self
selector:#selector(updateView:)
userInfo:nil
repeats:YES];
- (void)updateView:(NSTimer *)theTimer
{
if (index < [textArray count])
{
self.textView.text = [self.textArray objectAtIndex:index];
self.imageView.image = [self.imagesArray objectAtIndex:index];
index++;
} else {
index = 0;
}
I want to pause and resume timer when play/pause button is pressed in mainviewcontroller. How can i do that.

NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval:2.6
target:self
selector:#selector(updateView:)
userInfo:nil
repeats:YES];
[myTimer invalidate];
/*
Stops the receiver from ever firing again and requests its removal from its run loop.
*/
[myTimer fire];
/*
You can use this method to fire a repeating timer without interrupting its regular firing schedule. If the timer is non-repeating, it is automatically invalidated after firing, even if its scheduled fire date has not arrived.
*/

First you have to keep a reference of your timer in your interface-file:
NSTimer *myTimer;
In the implementation file you can simply connect and then refer to it:
myTimer = [NSTimer scheduledTimerWithTimeInterval:2.6
target:self
selector:#selector(updateView:)
userInfo:nil
repeats:YES];
To stop the timer call:
[myTimer invalidate];
To start it again:
[myTimer fire];
See NSTimer Class Reference for more info about the NSTimer Class.

Related

How do I set a NSTimer to stop if a certain action is running?

I have a popup in a custom view controller that is presented after 1 minute thanks to my NSTimer.
My NSTimer code:
[NSTimer scheduledTimerWithTimeInterval:60.0f
target:self selector:#selector(methodB:) userInfo:nil repeats:YES];`
The method that reveals the popup
- (void) methodB:(NSTimer *)timer
{
//Do calculations.
[self showPopupWithStyle:CNPPopupStyleFullscreen];
}
I'm trying to set the NSTimer to stop running if the [self showPopupWithStyle:CNPPopupStyleFullscreen]; is currently open, running or active.
Then I would like to start the NSTimer back up again if the popup view controller is NOT open, running or active.
Any help, samples or examples would be greatly appreciated!
My project is written in Objective-C.
EDIT:
I tried the answers in the suggested "possibly similar" answer and it doesn't seem to work for what I am doing. How do I stop NSTimer?
This seems to do the trick.
#property (nonatomic, strong) CNPPopupController *popupController;
- (void)_timerFired:(NSTimer *)timer;
#end
NSTimer *_timer;
- (void)viewDidLoad {
[super viewDidLoad];
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:10.0f
target:self
selector:#selector(_timerFired:)
userInfo:nil
repeats:YES];
}
}
- (void)_timerFired:(NSTimer *)timer {
if ([_timer isValid]) {
[self showPopupWithStyle:CNPPopupStyleFullscreen];
[_timer invalidate];
}
_timer = nil;
NSLog(#"ping");
}
If you want to restart the timer just add this code where you'd like the action to start back up.
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:10.0f
target:self
selector:#selector(_timerFired:)
userInfo:nil
repeats:YES];
}
Hope this helps! :)

Xcode cocoa simultaneously update interface by timer and continuous action by slider

I need to update some user interface objects by timer, but when I touch slider with continuous action everything freeze beside slider.
in iOS this version work fine, but in mac os x some problems :(
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
tick = 0;
[NSTimer scheduledTimerWithTimeInterval:0.25f
target:self
selector:#selector(timerTick)
userInfo:nil
repeats:YES];
}
- (void)timerTick
{
tick++;
[self.labelTest setIntegerValue:tick];
}
- (IBAction)sliderAction:(id)sender
{
// do something
NSLog(#"%g", [self.sliderMain doubleValue]);
}
You should add your timer to main run loop:
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
And also you should create instance variable or property, for example:
#property (strong, nonatomic) NSTimer *timer;
And before you create timer I would recomentded you to use lazy initialization:
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:0.25f
target:self
selector:#selector(timerTick)
userInfo:nil
repeats:YES];
}
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
And when you close the app or the app goes to background you can invalidate timer:
[self.timer invalidate];
self.timer = nil;
Hope this help.

NSTimer Not Stopping When Invalidated

I have the following code in my .h file:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <AVFoundation/AVFoundation.h>
#import <MapKit/MapKit.h>
#interface LandingController : UIViewController<CLLocationManagerDelegate> {
CLLocationManager *LocationManager;
AVAudioPlayer *audioPlayer;
}
#property (nonatomic, retain) NSTimer *messageTimer;
- (IBAction)LoginButton:(id)sender;
#end
I have the following code in my .m file:
#interface LandingController ()
#end
#implementation LandingController
#synthesize messageTimer;
- (void)checkForMessages
{
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"BINGO:"
message:#"Bingo This Works"
delegate:nil
cancelButtonTitle:#"Okay"
otherButtonTitles:nil];
[alert show];
}
- (IBAction)LoginButton:(id)sender {
if ([UserType isEqualToString:#"Owner"]) {
if (messageTimer){
[self.messageTimer invalidate];
self.messageTimer = nil;
}
} else {
if (!messageTimer){
self.messageTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(checkForMessages)
userInfo:nil
repeats:YES];
}
}
}
#end
But my timer doesn't want to stop when I call the invalidate.
The LoginButton is only pressed twice, once when the strResult is = to "Guard" and then the application changes it to be equal to "Owner" and the user presses the login button again, so I don't think I'm setting multiple timers.
After pressing the login button and starting the timer I segue to another view and then segue back to press the login button once more which is when I want the timer to stop. Do I need to do anything special to get the messageTimer since I switched views for a moment and then came back?
Any ideas?
Thanks!
You need to call [self.messageTimer invalidate] on the same thread on which you created the timer. Just make sure that the timer is created and invalidated on main thread.
dispatch_async(dispatch_get_main_queue(), ^{
if ([UserType isEqualToString:#"Owner"]) {
[self.messageTimer invalidate];
self.messageTimer = nil;
} else {
self.messageTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(checkForMessages)
userInfo:nil
repeats:YES];
}
});
NSTimer is retained by NSRunLoop, so the only way I see your issue happening is if you're actually creating more than one timer and invalidating only what you have reference to.
Example:
if(!timer)
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:(self) selector:#selector(processTimer) userInfo:nil repeats:YES];
Have you try to put repeat as No
self.messageTimer = [NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(checkForMessages)
userInfo:nil
repeats:NO];
If the code at the end (starting with if) is called twice with UserType != Owner, you create a new timer without invalidating the old one. Now two timers are running. If the code executes a third time, you will add a third timer and so on. Executing the code with UserType == Owner only invalidates the last timer and even it is called repeatly, it does not invalidate older timers.
You have a timer leak. ;-)
How about put an NSLog in your checkForMessages method? It would be easier to check if there's really only 1 timer.
(I'd rather put this in a comment, but I don't have that much reputation....)
I have an approach for stopping or deactivate the timer, Before apply this make sure that you tried all the cases as mentioned above so you can also understand that why this approach used at last.
// Instead of self use NSTimer class, it will not provide you any crash and in selector placed any empty function and setRepeats to NO
self.messageTimer = [NSTimer scheduledTimerWithTimeInterval:100.0
target:NSTimer selector:#selector(emptyFunctionCalling)
userInfo:nil
repeats:NO];
[self.messageTimer invalidate];
self.messageTimer = nil;
So whenever the case occured that timer will not stopping then entering in this code the timer will stops permanently.
Its weird but invalidating passed timer reference and created timer reference worked for me.
delayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateDelayLable:) userInfo:nil repeats:YES];
-(void)updateSendDataDelayLable:(NSTimer*)timer{
delayValueForGNSS--;
if (delayValueForGNSSSend==0) {
[timer invalidate];
timer = nil;
[delayTimer invalidate];
delayTimer = nil;
}
}

How to stop NSTimer started on button click in this timer callback method

I am having problems with stoping NSTimer started on button click. [timer invalidate] and timer = nil; just do nothing neither when I am trying to stop it viewWillDisappear nor in method invoked by method which is being invoked by this timer. However when I start my timer in viewWillAppear and invalidate it in viewWillDisappear everything is fine.
I suppose there might be an issue in thread I am starting the timer from. Can you help with that?
I looked through all answers here regarding NSTimer not stopping, but they didn't help to solve the problem.
The way I initialize my timer:
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(oneSecondPassedSinceRoundStarted) userInfo:nil repeats:YES];
The ways I tried to stop it:
[self.timer invalidate];
[timer invalidate];
It's funny how quick you can answer your own question after you asked for a help. No matter how long you have been struggling to find the answer before by yourself:
[self performSelectorOnMainThread:#selector(stopTimer) withObject:nil waitUntilDone:YES];
And the selector:
- (void) stopTimer
{
[timer invalidate];
timer = nil;
}
I have created and tested this:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(oneSecondPassedSinceRoundStarted:) userInfo:nil repeats:YES];
}
-(void)oneSecondPassedSinceRoundStarted:(NSTimer *)time {
// Do what You want
NSLog(#"CALLING!");
}
-(IBAction)buttonAction:(id)sender {
NSLog(#"Stop timer!");
[myTimer invalidate];
myTimer = nil;
}
And it is working nice.
Note: You forget to add colon after oneSecondPassedSinceRoundStarted.

Application crashing due to Nested NSTimer and view switch

here is the code
-(void)manageAnimation:(Properties *)prop
{
//if(bounceTimer.isValid)
// [bounceTimer invalidate];
bounceTimer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:#selector(animate) userInfo:nil repeats:YES];
}
-(void)animate{
static float t = 0;
float d = .5;
static float fValue = 0;
fValue = [self easeOutBounce:t andB:0 andC:34 andD:d];
[self setNeedsDisplay];
t += .5/10;
if(t > d){
[bounceTimer invalidate];
t = 0;
fValue = 0;
}
}
I am calling manageAnimation after each second. When i click info button on screen it flips to settings screen, when i click done button on settings screen to go back to main screen the application crashes. If i comment out the code
//bounceTimer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:#selector(animate) userInfo:nil repeats:YES];
Then application works ok. I am not sure whats going on, also i found that when i switched to settings view these timers are stopped.
Why would you call manageAnimation every second? If you do that then you create a new timer every time and still have the previous timer running.
Since the timer repeats you can just let it run instead of creating a new one every time you call manageAnimation.
Also you need to retain the timer you create. I'm assuming that bounceTimer is an ivar, so you need this in your .h file:
#property (nonatomic, retain) NSTimer *bounceTimer;
And then manageAnimation needs to use the setter:
-(void)manageAnimation:(Properties *)prop
{
if (self.bounceTimer == nil) {
self.bounceTimer = [NSTimer scheduledTimerWithTimeInterval:.05 target:self selector:#selector(animate) userInfo:nil repeats:YES];
}
}
And in animate where you invalidate the timer, set the ivar to nil to release it:
[bounceTimer invalidate];
self.bounceTimer = nil;