Question

I have an NSTimer which I want to update a label every second. My code is:

- (IBAction)OnClickEmergencyButton:(id)sender
{
    emergencyAlertTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(emergencyTimer) userInfo:nil repeats:YES];
    [emergencyAlertTimer fire];
}

- (void)emergencyTimer
{
    int i = 0;
    _emergencyAlertTriggerTimerLabel.text = [NSString stringWithFormat:@"%d", ++i];
}

When I ran it, the label displayed "1" initially and then stopped.

I want the label to continuously count up every second, like "1", "2", "3", ...

Était-ce utile?

La solution

There is no issue with your timer. The issue is with the variable declaration inside the emergencyTimer, you declared it as a local variable. So each time when the timer fires the variable will be initialized to 0 again. So declare the variable as static, so that it can preserve the value.

Change the method like:

-(void)emergencyTimer
{
    static int timeValue = 0;
    _emergencyAlertTriggerTimerLabel.text = [NSString stringWithFormat:@"%d",++timeValue];
}

Why static variable and Why not instance variable ?

I didn't used instance variable, for keeping the variable "Scope" safe. If I put it as an instance variable, it can be accessed by other methods of the same class, if there is no need of that functionality, I think using a static variable will be better.

Autres conseils

Issue is with this code

int i=0;

Every time when timer method gets called, the integer i gets initialized and label will be displayed as "1" always.

Make this variable global or static to fix your issue.

Remove int i=0; from your timer action method because it will always have a value of zero. You should be using an instance variable (@property) to store the timerCounter and increment that and use it to populate the label.

At some point in time you need to invalidate the timer. This is particularly important to do before you create a new timer and replace the reference to the old timer. Currently, if you press the button twice, you will then have 2 timers running and your label will increment twice a second...

@property (nonatomic, assign) NSInteger timerCounter;

- (IBAction)OnClickEmergencyButton:(id)sender {
    [emergencyAlertTimer invalidate];
    emergencyAlertTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(emergencyTimer) userInfo:nil repeats:YES];
    [emergencyAlertTimer fire];
}

- (void)emergencyTimer {
    _emergencyAlertTriggerTimerLabel.text = [NSString stringWithFormat:@"%d", self.timerCounter];
    self.timerCounter++;
}

You should also invalidate the timer when the view is removed from display / deallocated.

Always timer get called emergencyTimer but your value of i won't changed because it's an local variable, scope of i will remain at end of function call. Try this with static variable which remain globally...

-(void)emergencyTimer{
    static int i=0; // initialize at first time only..
    _emergencyAlertTriggerTimerLabel.text = [NSString stringWithFormat:@"%d",++i];
   if ( i == 100) 
       [ emergencyAlertTimer invalidate] // stop at certain condition
}

Firstly everyone is right you will only display a 0 no matter what you do currently so use an instance variable.

With regards to the only firing once, instead of [NSTimer fire] try this:

emergencyAlertTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(emergencyTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:emergencyAlertTimer forMode:NSRunLoopCommonModes];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top