Update UILabel continuously — Objective-c - ios

I'm trying to display the count of a timer in a UILabel. The timer works fine but I'm not able to update the label. The NSTimer is set up like this in Class1.
- (void)startTimer {
int timerCount = 5;
timer = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(timerDecrement)
userInfo:nil
repeats:YES];
[timer fire];
}
- (void)timerDecrement {
Class2 *cls2 = [[Class2 alloc] init];
timerCount = timerCount-1;
[cls2 updateTimeLeftLabel];
}
+ (int)getTimerCount {
return timerCount;
}
In Class2:
- (void)viewDidLoad {
if (timeLeftLabel == nil) {
timeLeftLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 70, 120, 30)];
timeLeftLabel.text = #"Time left";
[self.view addSubview:timeLeftLabel];
}
- (void)updateTimeLeftLabel {
NSLog(#"%#", [NSString stringWithFormat:#"%i",
[Class1 getTimerCount]]);
timeLeftLabel.text = [NSString stringWithFormat:#"Time left: %i",
[Class1 getTimerCount]];
}
The correct timer value is logged but the UILabel isn't updated at all. What's wrong?

Try to make timerCount as a #property of your class or static.

You create a new instance of the Class2 and do not present it. You should store instance of Class2 somewhere and work with it.

I needed to update count on my UIButton so i have done like this
-(void)viewDidLoad {
self.myLeagueTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateCountdown) userInfo:nil repeats: YES];
}
- (int)timeIndervalRemain {
NSDate *currentTime = [NSDate date];
return (TIME_INTERVAL - [currentTime timeIntervalSinceDate:self.startTime]);
}
-(void) updateCountdown {
if ([self timeIndervalRemain] > 0) {
self.title = [NSString stringWithFormat:#"%d", [self timeIndervalRemain]];
} else {
[self timeExpire];
}
}
-(void) timeExpire {
if (_myLeagueTimer) {
[_myLeagueTimer invalidate];
_myLeagueTimer = nil;
}
}

You can simply pass the time left to the method updating the UILabel as a parameter:
- (void)updateTimeLeftLabel:(NSInteger)timeLeft {
timeLeftLabel.text = [NSString stringWithFormat:#"Time left: %i",
timeLeft];
}
- (void)timerDecrement {
Class2 *cls2 = [[Class2 alloc] init];
timerCount = timerCount-1;
[cls2 updateTimeLeftLabel:timerCount];
}

Related

Keep label updating through segue

I have a small sample project i'm using to figure out how to implement this on my main project. This simple project has 2 VC's both with segues to each other.
On the initial VC is a button which leads to the TimerVC (both using the same class).
The TimerVC has a button and a label. When the button is pressed the label will increase by 1 every second.
If the timer is on and I segue back to the initial VC and then to the TimerVC the timer continues but the label stops updating.
How can I keep the label updating? The timer keeps going in the back-end but once the segue happens the label stops updating.
EDIT: Code provided below. The Timer is also more complex to represent a little of what I'm trying to do.
VC.H
NSTimer * timer;
NSTimer * updateTimer;
#property (weak, nonatomic) IBOutlet UIButton *idleOutler;
- (IBAction)idleAttack:(id)sender;
VC.M
int enemy001Hp = 100;
int deadEnemy = NO;
int noHealth = 0;
bool enemy001Active = NO;
- (void) enemy1 {
enemy001Active = YES;
self.enemyHpLabel.text = [NSString stringWithFormat:#"%i", enemy001Hp];
}
- (void) enemyDamageTimer {
if (enemy001Active == YES) {
enemy001Hp -= 50;
self.enemyHpLabel.text = [NSString stringWithFormat:#"%i",enemy001Hp];
}
}
- (void) updateLabelTimer {
if (enemy001Active == YES) {
self.enemyHpLabel.text = [NSString stringWithFormat:#"%i", enemy001Hp];
}
}
- (void) stopTimer {
[timer invalidate];
timer = nil;
self.enemyHpLabel.text = [NSString stringWithFormat:#"0"];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self enemy1];
if (enemy001Active) {
self.enemyHpLabel.text = [NSString stringWithFormat:#"%i", enemy001Hp];
} else if (enemy002Active == YES) {
self.enemyHpLabel.text = [NSString stringWithFormat:#"%i", enemy002Hp];
}
}
- (IBAction)idleAttack:(id)sender {
idleOn = YES;
self.idleOutler.hidden = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(enemyDamageTimer) userInfo:nil repeats:YES];
updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateLabelTimer) userInfo:nil repeats:YES];
if (enemy001Active == YES) {
if (enemy001Hp <= 0) {
[self enemy2];
enemy001Active = NO;
enemy002Active = YES;
}
} else if (enemy002Active == YES) {
if (enemy002Hp <= 0) {
self.enemyHpLabel.text = [NSString stringWithFormat:#"0"];
enemy002Hp = 0;
enemy002Active = NO;
[self stopTimer];
}
}
}

Start and Stop functionality of StopWatch is not coordinated iOS

I am creating a stopwatch and the start and stop functionality is not coordinated. When the timer stops, it doesn't start where it left of.
The code looks like this:
self.endDate = [NSDate dateWithTimeIntervalSinceNow:12.0f*60.0f];
-(void)startPressed:(id)sender{
if(!_running){
_running = TRUE;
[sender setTitle:#"Stop" forState:UIControlStateNormal];
if (_stopTimer == nil) {
_stopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(changeTimer:)
userInfo:nil
repeats:YES];
}
}else{
_running = FALSE;
[sender setTitle:#"Start" forState:UIControlStateNormal];
[_stopTimer invalidate];
_stopTimer = nil;
}
}
- (void)changeTimer:(NSTimer*)timer {
_timeInterval = [self.endDate timeIntervalSinceNow];
self.timerControl1.minutesOrSeconds = ((NSInteger)_timeInterval)%60;
self.timerControl2.minutesOrSeconds = (NSInteger)(_timeInterval/60.0f);
self.timerControl3.minutesOrSeconds = ((NSInteger)_timeInterval)%60;
}
I know it is because of timeIntervalSinceNow. But, how to change this? Need some guidance on this.
The problem:
When you stop the stopwatch and start it again after 3s for example, it shld still start back from the same timing. but both my code, the start and stop timing are different, they are starting from a different timing. Need help to solve this.
don't use the endDate in changeTimer but use the endDate only to init the timer
#import "RimsViewController.h"
#interface RimsViewController ()
#property(weak) IBOutlet UILabel *label;
#property(strong) NSDate *endDate;
#end
#implementation RimsViewController {
BOOL _running;
NSTimeInterval _timeInterval;
NSTimer *_stopTimer;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.endDate = [NSDate dateWithTimeIntervalSinceNow:10*60];
_timeInterval = [self.endDate timeIntervalSinceNow];
}
-(IBAction)startPressed:(id)sender{
if(!_running){
_running = TRUE;
[sender setTitle:#"Stop" forState:UIControlStateNormal];
if (_stopTimer == nil) {
_stopTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(changeTimer:)
userInfo:nil
repeats:YES];
}
}else{
_running = FALSE;
[sender setTitle:#"Start" forState:UIControlStateNormal];
[_stopTimer invalidate];
_stopTimer = nil;
}
}
- (void)changeTimer:(NSTimer*)timer {
_timeInterval -= 1;// [self.endDate timeIntervalSinceNow];
NSUInteger secs = _timeInterval;
int h = (NSUInteger)secs/3600;
secs-=h*3600;
int m = (NSUInteger)secs/60;
secs-=m*60;
int s = secs;
self.label.text = [NSString stringWithFormat:#"%d / %d / %d", h, m, s];
}
#end

How to hide Text from UILabel in IOS

I'm trying to display a set of numbers on a UILabel sequentially.
For example: I have an array with 5 numbers and each time I want one number from the array to be displayed for 2 seconds on the screen then disappear and then the next number…
This is what i have done so far, but it is not quite what I want. The code below just displays the last number in the array for 2 seconds and then disappears.
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray* myArray = [NSMutableArray array];
for (int i=0; i<5; i++) {
NSNumber *temp;
temp = [myArray objectAtIndex:i];
[self displayNumber:temp];
[myLabel setHidden:NO];
}
}
-(void) displayNumber: (NSNumber *) myNumber{
myLabel.text = [NSString stringWithFormat:#"%#", myNumber];
NSTimer *myTimer;
myTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(hideLabel) userInfo:Nil repeats:NO];
}
-(void) hideLabel{
[myLabel setHidden:YES];
}
I thought about having 5 functions and each gets called sequentially after 2 seconds, but that is very inefficient.
Are there any other ways I can do this?
Change this method
Hope it will works for you what you want
1) Define
NSMutableArray* myArray , int repeatCount; and NSTimer *myTimer in .h file and set its property;
2)
-(void)viewDidLoad
{
[super viewDidLoad];
//This will initialize your timer
myTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(showLabel) userInfo:Nil repeats:NO];
//This will trigger your timer
[myTimer fire];
//Your timer will run in a loop
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
myArray = [NSMutableArray array];
}
-(void) displayNumber: (NSNumber *) myNumber{
myLabel.text = [NSString stringWithFormat:#"%#", myNumber];
}
-(void) showLabel{
if(repeatCount >= [myArray count])
{
repeatCount = 0;
}
NSNumber *temp = [myArray objectAtIndex:repeatCount];
repeatCount ++;
[self displayNumber:temp];
[myLabel setHidden:NO];
}
I think, that you can use timer with counter.
Create 3 properties:
#property (nonatomic, assign) int counter;
#property (nonatomic, strong) NSArray *array;
#property (nonatomic, strong) NSTimer *timer;
Set them in viewDidLoad: and start timer(with repetition):
- (void)viewDidLoad {
[super viewDidLoad];
_counter = 0;
_array = #[#0, #1, #2, #3, #4, #5];
_timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(nextLabel) userInfo:Nil repeats:YES];
}
Update label:
- (void)nextLabel{
if (_counter == [_array count]) {
//stop in the end of array
[_timer invalidate];
return;
}
[_label setText:[NSString stringWithFormat:#"%#", _array[_counter]]];
_counter++;
}
Pass the array with NSNumber instances to the below method
- (void)updateLabelWithArray:(NSMutableArray *)array
{
if ([array count] != 0)
{
myLabel.text = [NSString stringWithFormat:#"%#", [array firstObject]];
[array removeObjectAtIndex:0];
[self performSelector:#selector(updateLabelWithArray:)
withObject:array
afterDelay:2.0f];
}
}
This should do.
Try this:
// Initialize the timer when you want to change the first number
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(changeNumber:) userInfo:#{#"currentNumber" : [NSNumber numberWithInt:0]} repeats:NO];
-(void)changeNumber:(NSTimer *)timer
{
NSDictionary * dictionary = [timer userInfo];
int number = [(NSNumber *)[dictionary objectForKey:#"currentNumber"] integerValue];
if (number < [numbersArray count])
{
myLabel.text = [NSString stringWithFormat:#"%#", [numbersArray objectAtIndex:number]];
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(changeNumber:) userInfo:#{#"currentNumber" : [NSNumber numberWithInt:number + 1]} repeats:NO];
}
}
try this hope this helps u .. :)
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[super viewDidLoad];
myArray = [[NSMutableArray alloc]initWithObjects:[NSNumber numberWithInt:3],[NSNumber numberWithInt:5],[NSNumber numberWithInt:6],[NSNumber numberWithInt:7],[NSNumber numberWithInt:10], nil]; //your array contains any number you want
index = 0; //showing the numbers from 0th index to last indx
[self.myLabel setHidden:NO];
[NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(DisplayFortwoSec) userInfo:nil repeats:YES];//call the method reguraly for 2 sec
}
- (void)DisplayFortwoSec
{
[self.myLabel setHidden:YES];
if(index == ([myArray count] - 1))
index = 0;//other stuffs to come out of loop like invalidating the timer
[self.myLabel setHidden:NO];
NSNumber *num = [myArray objectAtIndex:index];
NSString *strNum = [num stringValue];
self.myLabel.text = strNum;
[self.myLabel setHidden:NO];
index ++;
}

How to get a function to pause until the NSTimer selector is finished?

I have an NSTimer in another function but I want to be able to wait for the NSTimer to become invalidated before continuing on with the code is there a way to do this?
- (IBAction)addLifePoints:(UIButton *)sender
{
[[ARCHDuelCalculator sharedARCHDuelCalculator] setLifePointDelta:[NSNumber numberWithInt: [self.hiddenTextField.text intValue]]];
[[ARCHDuelCalculator sharedARCHDuelCalculator] setAddOrSubstract: YES];
[[ARCHDuelCalculator sharedARCHDuelCalculator] applyingDeltaToLifePointsByDelta];
// This will animate the life points
animationTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(animateLifePoints) userInfo:nil repeats:YES];
// This is where we bring it back to the view controller
self.duelistOneLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistOneLifePoints stringValue];
self.duelistTwoLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistTwoLifePoints stringValue];
self.hiddenTextField.text = #"";
[self syncTextField: self.hiddenTextField];
[self.hiddenTextField resignFirstResponder];
}
- (void) animateLifePoints
{
NSNumber *sections = [[ARCHDuelCalculator sharedARCHDuelCalculator] getLifePointSections];
for(int timer = 0; timer < 100; ++timer)
{
self.duelistOneLifePoints.text = [[[ARCHUtilities sharedARCHUtilities] subtractTwoNSNumbersByDataType:#"int" firstNumber:[NSNumber numberWithInt: [self.duelistOneLifePoints.text intValue]] secondNumber:sections] stringValue];
if ((timer % 14) == 0)
{
[self playLifePointSound:#"mainLifePointSound" typeOfFile:#"mp3"];
}
}
[animationTimer invalidate];
}
hope this works:
-split addLifePoints into 2 methods.
-put code after the nstimer in another method (newMethod)
-call newMethod right after the nstimer is invalidated.
- (IBAction)addLifePoints:(UIButton *)sender
{
[[ARCHDuelCalculator sharedARCHDuelCalculator] setLifePointDelta:[NSNumber numberWithInt: [self.hiddenTextField.text intValue]]];
[[ARCHDuelCalculator sharedARCHDuelCalculator] setAddOrSubstract: YES];
[[ARCHDuelCalculator sharedARCHDuelCalculator] applyingDeltaToLifePointsByDelta];
// This will animate the life points
animationTimer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(animateLifePoints) userInfo:nil repeats:YES];
}
- (void) animateLifePoints
{
NSNumber *sections = [[ARCHDuelCalculator sharedARCHDuelCalculator] getLifePointSections];
for(int timer = 0; timer < 100; ++timer)
{
self.duelistOneLifePoints.text = [[[ARCHUtilities sharedARCHUtilities] subtractTwoNSNumbersByDataType:#"int" firstNumber:[NSNumber numberWithInt: [self.duelistOneLifePoints.text intValue]] secondNumber:sections] stringValue];
if ((timer % 14) == 0)
{
[self playLifePointSound:#"mainLifePointSound" typeOfFile:#"mp3"];
}
}
[animationTimer invalidate];
[self newMethod]; //////////////////// ADD THIS LINE ALSO, continue code
}
-(void)newMethod{
//...so continue code...
// This is where we bring it back to the view controller
self.duelistOneLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistOneLifePoints stringValue];
self.duelistTwoLifePoints.text = [[ARCHDuelCalculator sharedARCHDuelCalculator].duelistTwoLifePoints stringValue];
self.hiddenTextField.text = #"";
[self syncTextField: self.hiddenTextField];
[self.hiddenTextField resignFirstResponder];
}

iOS NSTimer firing twice

Hi I'm trying to use NSTimer to create a countdown which and view this using a label. the problem is the label goes down in two's and i don't know why. any ideas?
heres my code
- (void)viewDidLoad
{
NSLog(#"%#", self.chosenTime);
[self startGame];
[super viewDidLoad];
NSString *timeString = self.chosenTime;
self.timer = [timeString intValue];
self.countdown.text = timeString;
// Do any additional setup after loading the view.
}
- (void)startGame
{
[self introCountdown];
[self performSelector:#selector(goAnimation) withObject:nil afterDelay:3.0];
NSString *timeString = self.chosenTime;
self.timer = [timeString intValue];
[self performSelector:#selector(startCountdown) withObject:nil afterDelay:4.0];
}
- (void)startCountdown
{
//self.countdownTimer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(decrementTimer:) userInfo:nil repeats:YES];
self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.00 target:self selector:#selector(decrementTimer:) userInfo:nil repeats:YES];
}
- (void)decrementTimer:(NSTimer *)timer
{
if(self.timer > 0)
{
self.timer = self.timer - 1;
self.countdown.text = [NSString stringWithFormat:#"%d", self.timer];
}
else
{
[self.countdownTimer invalidate];
self.countdownTimer = nil;
}
}
This code seems to be correct. May be you are changing label's text from somewhere else?
Sorry for the misinterpretation, the code is correct, it seems a UI problem or handling label from somewhere else, attach your source with xib's if possible

Resources