How to make a button appear and disappear throughout a timer - ios

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.

Related

Values from 1 to 100 in label change when view is loaded in objective c

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

NSTimer stops my image from moving

When I hold down on a button my image will move to a direction.
The game objective is that they are going to move image to hit another image, and to do that I'm using an NSTimer.
Then they also have another NSTimer because they only have 15 seconds on them to hit the other image. If they don't the game will [self gameover] but, the NSTimer that counts the 15 seconds is started and I move the image the image moves a bit and then it goes back to center again.
When I delete the countdown timer, the image does not go back to center after I stop pressing the button but it stops on its current position.
And that's what I want it to do while I'm using the countdown timer as well.
Code:
-(void)goLeft
{
ball.center = CGPointMake(ball.center.x -5, ball.center.y);
}
-(IBAction)left
{
goLeft = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(goLeft) userInfo:nil repeats:YES];
if (goLeft == nil) goLeft = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(goLeft) userInfo:nil repeats:YES];
}
-(IBAction)stopLeft
{
[goLeft invalidate];
goLeft = nil;
}
//And heres the timer :
-(IBAction)doCountdown: (id)sender;{
if (countdownTimer)
return;
remainingTicks = 25;
[self updateLabel];
countdownTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: #selector(handleTimerTick) userInfo: nil repeats: YES];
}
-(void)handleTimerTick
{
remainingTicks--;
[self updateLabel];
if (remainingTicks <= 0) {
[countdownTimer invalidate];
countdownTimer = nil;
}
}
-(void)updateLabel
{
theLabel.text = [[NSNumber numberWithUnsignedInt: remainingTicks] stringValue];
}

NSTimer move UIImageView faster

I use an NSTimer to move a UIImageView every 1 second, I want to decrease the time every 2 seconds from 1 to 0.5 as result the image will move faster inside the view. Any ideas will be very help full.
This is the timer that i use for moving the UIImageView
float obstaclesSpeed = 1.0;
movementTimer = [NSTimer scheduledTimerWithTimeInterval:obstaclesSpeed target:self selector:#selector(updateSpeed) userInfo:nil repeats:YES];
This is my code
-(void)updateSpeed {
obstaclesSpeed = obstaclesSpeed / 2;
[self startMoveObstacles];
}
I believe something I do wrong
Are you wanting to move the image every 2 seconds, or make it move increasingly faster? It won't move faster, if you only move it every 2 seconds.
You can read the docs for NSTimer, but to take some of the headache out of it, here's some examples of how to use NSTimer for this.
If you're wanting to move it every two seconds, you can do the following.
- (void) startTimer {
[_myTimer invalidate];
_myTimer = nil;
_myTimer = [NSTimer timerWithTimeInterval:2. target:self selector:#selector(respondToTimer:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_myTimer forMode:NSRunLoopCommonModes];
}
- (void)respondToTimer:(NSTimer*)timer {
//Code to move your UIImageView
}
If you're wanting to move it increasingly faster, you can do the following.
- (void) startTimer {
[_myTimer invalidate];
_myTimer = nil;
_myTimer = [NSTimer timerWithTimeInterval:_timeInterval target:self selector:#selector(respondToTimer:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:_myTimer forMode:NSRunLoopCommonModes];
}
- (void)respondToTimer:(NSTimer*)timer {
//Code to move your UIImageView
_numberOfMoves++;
if (_numberOfMoves < MAX_MOVES) {
_timeInterval /= 2;
[self startTimer];
}
}

NSTimer automatically increases when I change view controller

In my viewController I inserted a timer for a calculation of numbers taken directly from my database of Parse.com.
The timer is working correctly, were inserted in viewDidAppear and in ViewDidDisappear in such a way as to lock the sequence when changing view controller.
The problem I have is that when I change the view controller with the Push the timer does not stop you give an example:
I open the application and the calculation is done correctly with the animation of NSTimer.
Change View, and then I go back with the back button to view where the timer at this point I see that the numbers contiunano to increase every time I change view and go back ...
Can you explain where I'm wrong?
-(void)viewDidAppear:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
[self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]];
self.title = NSLocalizedString(#"", nil);
[self animatelayertopoint:0];
[self AnimationMenuView:600];
[self QueryForViewPrincipal];
[self QueryForCollectionView];
[self ShowBadgeNumber];
[self Timer];
[collectionView reloadData];
}
-(void)Timer{
timer = [NSTimer scheduledTimerWithTimeInterval:0.012 target:self selector:#selector(CalcoloMediadiLaurea) userInfo:nil repeats:YES];
}
-(void) CalcoloMediadiLaurea{
PFUser *CurrentUser = [PFUser currentUser];
NSNumber *NumeroUndici = [NSNumber numberWithInt:11];
NSNumber *NumeroTre = [NSNumber numberWithInt:3];
NSNumber *ValoreMediaPonderata = [CurrentUser objectForKey:FF_USER_MEDIA_PONDERATA];
int FFValoreTre = [NumeroTre intValue];
int FFValoreUndici = [NumeroUndici intValue];
double MediaPonderata = [ValoreMediaPonderata doubleValue];
double RisultatoMoltiplicazioneValoriPonderataUndici;
RisultatoMoltiplicazioneValoriPonderataUndici = MediaPonderata * FFValoreUndici;
double RisultatoMediaLaurea;
RisultatoMediaLaurea = RisultatoMoltiplicazioneValoriPonderataUndici / FFValoreTre;
CalcoloMediaLaureaLabel.text = [NSString stringWithFormat:#"%.1f", FFTickValoreMediaLaurea ];
FFTickValoreMediaLaurea++;
if(FFTickValoreMediaLaurea > RisultatoMediaLaurea){
[timer invalidate];
timer = nil;
}
}
-(void)viewDidDisappear:(BOOL)animated {
[self animatelayertopoint:0];
[self AnimationMenuView:600];
[self CalcoloMediadiLaurea];
}
The timer get rescheduled again on view did appear without getting invalidated to the previous one.You should make instance of timer in .h and then hold the reference of timer in it .And on view did appear when you are scheduling the timer just invalidate it and then schedule it again.
if([self.timer isValid])
{
[self.timer invalidate];
self.timer=nil;
self.timer=[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(CalcoloMediadiLaurea:) userInfo:nil repeats:YES];
}
This worked for me which is along the lines of the above answer but a little more explicitly stated.
- (void)viewWillAppear:(BOOL)animated
{
NSTimeInterval secondsBetween = [endDate timeIntervalSinceDate:currentTime];
secondsLeft = secondsBetween;
[self countdownTimer];
}
- (void)viewDidDisappear:(BOOL)animated
{
[self.timer invalidate];
self.timer = nil;
}
//Initiates timer
- (void)countdownTimer
{
[self.timer invalidate];
self.timer = nil;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
}
It's because you are creating new timers without invalidating old ones. The timers don't get invalidated automatically, you have to do it yourself. So if U go on second view and return before your invalidate condition is true you will create new timer and have two of them :)... And so on.

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

Resources