It is a really odd situation and I have never had a problem like this, and I would really appreciate any help that I get on this post. I have made a simple game. I will give .h and .m below.
Game30s.h :
//
// Game30s.h
// Speedy
//
// Created by Ajay Venkat on 15/10/2014.
// Copyright (c) 2014 AJTech. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface Game30s : UIViewController {
IBOutlet UILabel *scorelabel;
IBOutlet UIButton *bar1;
IBOutlet UIButton *bar2;
BOOL isCracked;
BOOL isCracked2;
NSTimer *go;
NSTimer *collision;
IBOutlet UIImageView *wall;
IBOutlet UIButton *start;
IBOutlet UIButton *contin;
NSTimer *time;
NSTimer *timestart;
int timem;
IBOutlet UILabel *timemanage;
int score;
}
-(void)tensecs;
-(void)timetwo;
-(void)goRight;
-(void)col;
-(IBAction)Statt;
-(IBAction)Tap1;
-(IBAction)Tap2;
#property (nonatomic) BOOL gameCenterEnabled;
#property (nonatomic, strong) NSString *leaderboardIdentifier;
#end
Game30s.m :
//
// Game30s.m
// Speedy
//
// Created by Ajay Venkat on 15/10/2014.
// Copyright (c) 2014 AJTech. All rights reserved.
//
#import "Game30s.h"
#import GameKit;
#interface Game30s()
#end
#implementation Game30s {
int cracknum;
float speed;
int score2;
int totscore;
}
- (void)viewDidLoad {
[super viewDidLoad];
timestart = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timetwo) userInfo:nil repeats:YES];
contin.hidden = YES;
start.hidden = NO;
bar1.hidden = YES;
bar2.hidden = YES;
[self authenticateLocalPlayer];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(IBAction)Tap1 {
int w = ([[UIScreen mainScreen] bounds].size.width);
int h = ([[UIScreen mainScreen] bounds].size.height);
w = w / 2;
int r1x = (arc4random() %240) + w ;
int r1y = (arc4random() %h);
bar1.center = CGPointMake(r1x, r1y);
speed = speed + 0.5;
score = score + 1;
}
-(IBAction)Tap2 {
int w = ([[UIScreen mainScreen] bounds].size.width);
int h = ([[UIScreen mainScreen] bounds].size.height);
w = w / 2;
int r2x = (arc4random() %240) + w ;
int r2y = (arc4random() %h);
speed = speed + 0.7;
bar2.center = CGPointMake(r2x, r2y);
score = score + 1;
}
-(void)goRight {
bar1.center = CGPointMake(bar1.center.x - speed, bar1.center.y);
bar2.center = CGPointMake(bar2.center.x - speed, bar2.center.y);
}
-(void)tensecs {
if (timem > 0) {
timem = timem - 1;
NSString* myString = [#(timem) stringValue];
timemanage.text = myString;
} else if (timem == 0) {
[timestart invalidate];
NSString* myString = [#(score) stringValue];
scorelabel.text = myString;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:score forKey:#"thirtysecond"];
bar1.hidden = YES;
bar2.hidden = YES;
start.hidden = NO;
start.enabled = YES;
contin.hidden = NO;
contin.enabled = YES;
[go invalidate];
[time invalidate];
}
}
-(void)col {
if (CGRectIntersectsRect(bar1.frame, wall.frame)) {
int r2x = (arc4random() %300) + 300 ;
int r2y = (arc4random() %375);
bar2.center = CGPointMake(r2x, r2y);
int r1x = (arc4random() %300) + 300 ;
int r1y = (arc4random() %375);
bar1.center = CGPointMake(r1x, r1y);
}
if (CGRectIntersectsRect(bar2.frame, wall.frame)) {
int r2x = (arc4random() %300) + 300 ;
int r2y = (arc4random() %375);
bar2.center = CGPointMake(r2x, r2y);
int r1x = (arc4random() %300) + 300 ;
int r1y = (arc4random() %375);
bar1.center = CGPointMake(r1x, r1y);
}
}
-(IBAction)Statt {
timem = 30;
score = 0;
contin.hidden = YES;
contin.enabled = NO;
time = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(tensecs) userInfo:nil repeats:YES];
bar1.hidden = NO;
bar2.hidden = NO;
int r2x = (arc4random() %300) + 300 ;
int r2y = (arc4random() %375);
bar2.center = CGPointMake(r2x, r2y);
int r1x = (arc4random() %300) + 300 ;
int r1y = (arc4random() %375);
bar1.center = CGPointMake(r1x, r1y);
cracknum = 0;
go = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(goRight) userInfo:nil repeats:YES];
collision = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(col) userInfo:nil repeats:YES];
speed = 3;
start.hidden = YES;
start.enabled = NO;
}
-(void)authenticateLocalPlayer{
// Instantiate a GKLocalPlayer object to use for authenticating a player.
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (viewController != nil) {
// If it's needed display the login view controller.
[self presentViewController:viewController animated:YES completion:nil];
} else {
if ([GKLocalPlayer localPlayer].authenticated) {
// If the player is already authenticated then indicate that the Game Center features can be used.
_gameCenterEnabled = YES;
// Get the default leaderboard identifier.
[[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) {
if (error != nil) {
NSLog(#"%#", [error localizedDescription]);
} else{
_leaderboardIdentifier = #"thirtysecondtappers";
}
}];
} else {
_gameCenterEnabled = NO;
}
}
};
}
#end
So this is the code. In the method -(void)tensecs I have said:
NSString* myString = [#(timem) stringValue];
timemanage.text = myString;
And I linked up everything properly! Then what happens in the simulator or on any device is that the time label counts down properly from 30 down to 0. But every time a number goes down for example 29 to 28 the UIImageViews reset to their home location on the screen.
See I show screen shots here.
I tried deleting that code
NSString* myString = [#(timem) stringValue];
timemanage.text = myString;
and then it did not do this anymore. I don't know why this is happening!
Summary:
The UIImageView is going back to its home location when the timer changes a number on label! Also I have added constraints to the image on the actual designer. Is this why?
This is because of auto layout. If you haven't turned off auto layout, and move views by setting their frames, then when the view needs to redraw (like when your score label changes), the view you moved will revert to the position defined by its constraints. To fix this, you either need to reposition your view by adjusting the constraints, or turn off auto layout.
Related
I am creating a game application in which I need to set timer of 2 minutes throughout the app screens in objective c.
I am creating it in viewDidLoad but it is creating a new instance every-time the view loads.
Here is the code which I am using :
#interface SomeViewController ()
{
int timerCounter;
NSTimer *timer;
}
#property (strong, nonatomic) IBOutlet UILabel *timerLbl;
#end
#implementation SomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self startCountdown];
}
- (void)startCountdown
{
timer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(countdownTimer:)
userInfo:nil
repeats:YES];
}
- (void)countdownTimer:(NSTimer *)timer
{
timerCounter--;
int minutes = timerCounter / 60;
int seconds = timerCounter % 60;
NSString *string = [NSString stringWithFormat:#"%02d", minutes];
NSString *string2 = [NSString stringWithFormat:#"%02d", seconds];
NSString *timeTotal = [string stringByAppendingString:#":"];
NSString *timeTotal2 = [timeTotal stringByAppendingString:string2];
_timerLbl.text = timeTotal2;
if (timerCounter <= 0) {
[timer invalidate];
}
}
You need to invalidate it whenever the VC deallocates
- (void)dealloc {
[timer invalidate];
}
//
The second VC may look like this
#import "ggViewController.h"
NSInteger timerCounter = 120; // declared global to hold the value
#interface ggViewController ()
{
NSTimer*timer;
}
#end
#implementation ggViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// instead of using selector use this inline callback
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:true block:^(NSTimer * timer) {
timerCounter--;
int minutes = timerCounter / 60;
int seconds = timerCounter % 60;
NSString *string = [NSString stringWithFormat:#"%02d", minutes];
NSString *string2 = [NSString stringWithFormat:#"%02d", seconds];
NSString *timeTotal = [string stringByAppendingString:#":"];
NSString *timeTotal2 = [timeTotal stringByAppendingString:string2];
_timerLbl.text = timeTotal2;
if (timerCounter <= 0) {
[timer invalidate];
}
}];
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
[timer invalidate];
}
- (IBAction)gg:(id)sender {
[self dismissViewControllerAnimated:true completion:nil];
}
#end
I have been trying for 2 days, searching high and low and cannot get the milliseconds to work. The hours, mins & seconds work fine, but milliseconds won't.
I've made a lapCounter, which counts UP and has no issues with the milliseconds.
Here is the working code for the lapCounter, which counts UP and the milliseconds work:
int hours = (UInt8)(elapsedTime /(60*60));
int mins = (UInt8)(elapsedTime / 60.0);
elapsedTime -= (mins * 60);
int secs = (UInt8)(elapsedTime);
elapsedTime -= (secs);
int mms = (UInt8)(elapsedTime * 100);
But I can't make the TimePicker Count DOWN, work.
This is what I have for the TimePicker Count DOWN:
int afterRemainder;
int remainder;
NSTimeInterval countDownTime;
NSTimer *countDownTimer;
bool startCountDown;
- (IBAction)startCountDownButton:(id)sender {
if (startCountDown == false) {
countDownTime = (NSTimeInterval)_datePicker.countDownDuration;
remainder = countDownTime;
afterRemainder = countDownTime - remainder%60;
countDownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateCountDown) userInfo:nil repeats:YES];
startCountDown = true;
}
-(void)updateCountDown {
afterRemainder --;
int hours = (int)(afterRemainder / (60 * 60));
int mins = (int)(afterRemainder / 60) - (60 * hours);
int secs = (int)(afterRemainder - (60 * mins) - (60 * hours * 60));
int mms = (int)(afterRemainder - (3600 * secs) - (mins * 60));
self.displayCountDown.text = [[NSString alloc] initWithFormat:#"%02d", hours];
self.displayCountDownMins.text = [[NSString alloc] initWithFormat:#": %02d", mins];
self.displayCountDownSecs.text = [[NSString alloc] initWithFormat:#"%02d", secs];
self.displayCountDownMMs.text = [[NSString alloc] initWithFormat:#":%2d", mms];
}
Try this:
#interface ViewController ()
#property (nonatomic, weak) IBOutlet UILabel *hours;
#property (nonatomic, weak) IBOutlet UILabel *minutes;
#property (nonatomic, weak) IBOutlet UILabel *seconds;
#property (nonatomic, weak) IBOutlet UILabel *millisecs;
#property (nonatomic, readwrite) NSTimeInterval counter;
#property (nonatomic, strong) NSTimer *timer;
#property (nonatomic, readwrite) int hoursInt;
#property (nonatomic, readwrite) int minutesInt;
#property (nonatomic, readwrite) int secondsInt;
#property (nonatomic, readwrite) int millisecsInt;
#end
#implementation ViewController
#define MS_COUNT_STEP 20.0 // Approx 50 fps
- (IBAction)countUpPressed:(id)sender {
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:MS_COUNT_STEP / 1000.0 target:self selector:#selector(countUp) userInfo:nil repeats:YES];
}
- (IBAction)countDownPressed:(id)sender {
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:MS_COUNT_STEP / 1000.0 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
}
- (void)countUp {
self.counter += (MS_COUNT_STEP / 1000.0);
}
- (void)countDown {
self.counter -= (MS_COUNT_STEP / 1000.0);
}
- (void)setCounter:(NSTimeInterval)counter {
_counter = counter;
[self updateUI];
}
- (void)updateUI {
NSTimeInterval counter = _counter;
self.hoursInt = counter / 3600;
counter -= ((int)self.hoursInt * 3600);
self.minutesInt = counter / 60;
counter -= ((int)self.minutesInt * 60);
self.secondsInt = (int)counter;
counter -= self.secondsInt;
self.millisecsInt = counter * 1000;
}
- (void)setHoursInt:(int)value {
if (value != _hoursInt) {
_hoursInt = value;
self.hours.text = [NSString stringWithFormat:#"%i", value];
}
}
- (void)setMinutesInt:(int)value {
if (value != _minutesInt) {
_minutesInt = value;
self.minutes.text = [NSString stringWithFormat:#"%i", value];
}
}
- (void)setSecondsInt:(int)value {
if (value != _secondsInt) {
_secondsInt = value;
self.seconds.text = [NSString stringWithFormat:#"%i", value];
}
}
- (void)setMillisecsInt:(int)value {
if (value != _millisecsInt) {
_millisecsInt = value;
self.millisecs.text = [NSString stringWithFormat:#"%i", value];
}
}
#end
Use CADisplayLink, instead NSTimer.
A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display.
With [NSTimer scheduledTimerWithTimeInterval:1 ...] the system can't draw the labels at that speed.
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];
}
}
}
Ok, so I've based my stopwatch app code from this tutorial right here http://iphonedev.tv/blog/2013/7/7/getting-started-part-3-adding-a-stopwatch-with-nstimer-and-our-first-class
I like the way it is set up, but I can't figure out how to add hundredths of a second to it, anyone know how to do this?
My ViewController.m file
#import "ViewController.h"
#import "Foundation/Foundation.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (NSTimer *)createTimer
{
return [NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:#selector(timerTicked:)
userInfo:nil
repeats:YES];
}
- (void)timerTicked:(NSTimer *)timer
{
_currentTimeInSeconds++;
self.timeLabel.text = [self formattedTime:_currentTimeInSeconds];
}
- (NSString *)formattedTime:(int)totalSeconds
{
int hundredths = totalSeconds % 60;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
return [NSString stringWithFormat:#"%02d:%02d:%02d.%02d", hours, minutes, seconds, hundredths];
}
- (IBAction)startButtonPressed:(id)sender
{
if (!_currentTimeInSeconds)
{
_currentTimeInSeconds = 0 ;
}
if (!_theTimer)
{
_theTimer = [self createTimer];
}
}
- (IBAction)stopButtonPressed:(id)sender
{
[_theTimer invalidate];
}
- (IBAction)resetButtonPressed:(id)sender
{
if (_theTimer)
{
[_theTimer invalidate];
_theTimer = [self createTimer];
}
_currentTimeInSeconds = 0;
self.timeLabel.text = [self formattedTime:_currentTimeInSeconds];
}
#end
Thanks again for anybody who can help!
First, you should change the name of your variable from _currentTimeInSeconds to _currentTimeInHundredths (or something shorter if you want).
Next, you need to update the logic in your - (NSString *)formattedTime:(int)totalSeconds method. Try something like this (changing totalSeconds to totalHundredths for the same reason as before).
int hours = totalHundredths / 360000;
int minutes = (totalHundredths - (hours * 360000)) / 6000;
int seconds = (totalHundredths - (hours * 360000) - (minutes * 6000)) / 100;
int hundredths = totalHundredths - (hours * 360000) - (minutes * 6000) - (seconds * 100);
I haven't tested the math on the numbers, but they should be right.
I have a UITabBarController with 3 view controllers connected to it. Everything works fine apart from when you switch from one view to another, the new view takes a moment to reload what it was doing. I know this isn't such a big deal but it just makes the app look a bit sloppy. Does anyone know how I can keep the app running in the background, or something so that it doesn't have to reload each time.
As you might have noticed I'm very new to Objective-C so I can understand if I'm being unclear but any help is really appreciated!
EDIT: FOR DAVID
This is the code for the stopwatch in the .m file:
#implementation StopwatchViewController
- (BOOL)prefersStatusBarHidden
{
return YES;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
isCounting = false;
}
- (IBAction)startOrStop:(id)sender
{
if (self->isCounting == false) {
self->isCounting = true;
[self startStopwatch];
} else {
self->isCounting = false;
[self stopStopwatch];
}
}
- (void)startStopwatch
{
[startStopButton setTitle:#"STOP" forState:UIControlStateNormal];
[self performSelector:#selector(stopwatch) withObject:self afterDelay:1.0];
}
- (IBAction)resetStopwatch:(id)sender
{
[self reset];
}
- (void)stopwatch
{
if (self->isCounting == false) {
return;
} else {
NSInteger hourInt = [hourLabel.text intValue];
NSInteger minuteInt = [minuteLabel.text intValue];
NSInteger secondInt = [secondLabel.text intValue];
if (secondInt == 59) {
secondInt = 0;
if (minuteInt == 59) {
minuteInt = 0;
if (hourInt == 23) {
hourInt = 0;
} else {
hourInt += 1;
}
} else {
minuteInt += 1;
}
} else {
secondInt += 1;
}
NSString *hourString = [NSString stringWithFormat:#"%02d", hourInt];
NSString *minuteString = [NSString stringWithFormat:#"%02d", minuteInt];
NSString *secondString = [NSString stringWithFormat:#"%02d", secondInt];
hourLabel.text = hourString;
minuteLabel.text = minuteString;
secondLabel.text = secondString;
CGRect hourFrame = self->hourBar.frame;
CGRect minuteFrame = self->minuteBar.frame;
CGRect secondFrame = self->secondBar.frame;
if ((NSInteger)hourFrame.size.height != hourInt) { // check if we need to modify
hourFrame.origin.y -= ((hourInt * 10.0) - hourFrame.size.height);
hourFrame.size.height = (hourInt * 10.0);
self->hourBar.frame = hourFrame;
}
if ((NSInteger)minuteFrame.size.height != minuteInt) { // check if we need to modify
minuteFrame.origin.y -= ((minuteInt * 4.0) - minuteFrame.size.height);
minuteFrame.size.height = (minuteInt * 4.0);
self->minuteBar.frame = minuteFrame;
}
if ((NSInteger)secondFrame.size.height != secondInt) { // check if we need to modify
secondFrame.origin.y -= ((secondInt * 4.0) - secondFrame.size.height);
secondFrame.size.height = (secondInt * 4.0);
self->secondBar.frame = secondFrame;
}
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(stopwatch) userInfo:nil repeats:NO];
}
}
- (void)stopStopwatch
{
[startStopButton setTitle:#"START" forState:UIControlStateNormal];
}
- (void)reset
{
[startStopButton setTitle:#"START" forState:UIControlStateNormal];
self->isCounting = false;
hourLabel.text = #"00";
minuteLabel.text = #"00";
secondLabel.text = #"00";
CGRect hourFrame = self->hourBar.frame;
CGRect minuteFrame = self->minuteBar.frame;
CGRect secondFrame = self->secondBar.frame;
hourFrame.size.height = 0;
minuteFrame.size.height = 0;
secondFrame.size.height = 0;
hourFrame.origin.y = 321.0;
minuteFrame.origin.y = 321.0;
secondFrame.origin.y = 321.0;
self->hourBar.frame = hourFrame;
self->minuteBar.frame = minuteFrame;
self->secondBar.frame = secondFrame;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SECOND EDIT FOR DAVID:
Changed the main parts of the code to look like this:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:YES];
[self swapFrames];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
[self updateBars];
}
- (void)stopwatch
{
if (self->isCounting == false) {
return;
} else {
hourInt = [hourLabel.text intValue];
minuteInt = [minuteLabel.text intValue];
secondInt = [secondLabel.text intValue];
if (secondInt == 59) {
secondInt = 0;
if (minuteInt == 59) {
minuteInt = 0;
if (hourInt == 23) {
hourInt = 0;
} else {
hourInt += 1;
}
} else {
minuteInt += 1;
}
} else {
secondInt += 1;
}
NSString *hourString = [NSString stringWithFormat:#"%02d", hourInt];
NSString *minuteString = [NSString stringWithFormat:#"%02d", minuteInt];
NSString *secondString = [NSString stringWithFormat:#"%02d", secondInt];
hourLabel.text = hourString;
minuteLabel.text = minuteString;
secondLabel.text = secondString;
[self swapFrames];
[self updateBars];
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(stopwatch) userInfo:nil repeats:NO];
}
}
- (void)updateBars
{
if ((NSInteger)hourFrame.size.height != hourInt) { // check if we need to modify
hourFrame.origin.y -= ((hourInt * 10.0) - hourFrame.size.height);
hourFrame.size.height = (hourInt * 10.0);
self->hourBar.frame = hourFrame;
}
if ((NSInteger)minuteFrame.size.height != minuteInt) { // check if we need to modify
minuteFrame.origin.y -= ((minuteInt * 4.0) - minuteFrame.size.height);
minuteFrame.size.height = (minuteInt * 4.0);
self->minuteBar.frame = minuteFrame;
}
if ((NSInteger)secondFrame.size.height != (secondInt * 4.0)) { // check if we need to modify
secondFrame.origin.y -= ((secondInt * 4.0) - secondFrame.size.height);
secondFrame.size.height = (secondInt * 4.0);
self->secondBar.frame = secondFrame;
}
}
- (void)swapFrames
{
hourFrame = self->hourBar.frame;
minuteFrame = self->minuteBar.frame;
secondFrame = self->secondBar.frame;
}
I separated the code so that just before the view appear it should update the bars. However, it did not work. I did some investigating by printing out the values of some of the variables at certain points. It appears that in viewWillAppear, secondBar.frame (and minuteBar, etc.) has updated to the correct height. However, in viewDidAppear, that value is reset to 0. This does not happen to secondInt, or secondFrame. Somewhere between those two methods the frame is reset but I cannot figure it out.
From what I understand, the frames for your properties self.hourBar, self.minuteBar and self.secondBar are set to 0 when you switch between tabs, and only update them every second.
If this is indeed the case, just set them to their correct values in your viewControllers viewWillAppear: method (assign them to some property in viewWillDisappear:).
As a sidenote, you seem to be coming from C++. The "->" notation is very uncommon for Objective-C, since properties are accessed with ".", and their corresponding instance variable with "->". Using the arrow notation will not call the auto-synthesised getter/setter methods of properties!
Also, is there a specific reason why you always create new NSTimer objects instead of setting repeats: to yes? Creating a timer and adding it to a runloop (which scheduledTimerWith:... does) is a relatively costly operation.