I'm working on an project were I have put in a progress bar and then set a button to start the progressbar when it is pressed. The thing is that I want to have the progress in 30min when you pressed the startbutton, so I need help to set it to 30 minutes.
Here is my code to setup the progressbar and startbutton
the m-file
- (IBAction)StartButton:(id)sender {
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(moreProgress)
userInfo:Nil repeats:YES];
[super viewDidLoad];
//progressbar start when button pressed
}
and then i got this for the time
//selector progress time
- (void) moreProgress {
myProgressView.progress += 0.001;
}
I think it's only a math problem.
First, myProgressView.progress can assume values from 0.0 to 1.0.
As you call moreProgress each second, you'll need to call it 1800 times for 30 minutes. Thus, myProgressView.progress should increase 1/1800 by second.
Change your code to:
- (void) moreProgress {
myProgressView.progress += 1.0/1800.0;
}
Hope it helps you! :)
1)Save the Current Time (You can save it to NSUserDefaults by example).
You can do something like That:
NSUserDefaults *user1 = [NSUserDefaults standardUserDefaults];
NSDate *currentDate = [NSDate date];
[user1 setObject:[NSNumber numberWithDouble:[currentDate timeIntervalSince1970]] forKey:#"time"];
[user1 synchronize];
2)schedule the call to your function like you did it
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(moreProgress)
userInfo:Nil repeats:YES];
3)Next in your function you need to update the progress view status with something like that:
//selector progress time
- (void) moreProgress {
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
NSDate *startTime = [NSDate dateWithTimeIntervalSince1970:[[user objectForKey:#"time"]doubleValue]];
NSTimeInterval elapsedTime = [startTime timeIntervalSinceNow];
float progress = (float)elapsed time / 30.0 * 60.0;
myProgressView.progress = progress;
if ((float)elapsedTime / 30 * 60 >= 1)
{
// The timer is end, you should stop it and do what you need
}
}
Note:
It s not safe to expect that
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(moreProgress)
will fire up each seconds. It s not guaranteed and not precise.
// This extension will help you. I'had used this extension and it really work for me.
extension UIProgressView {
#available(iOS 10.0, *)
func setAnimatedProgress(progress: Float = 1, duration: Float = 1, completion: (() -> ())? = nil) {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { (timer) in
DispatchQueue.main.async {
let current = self.progress
self.setProgress(current+(1/duration), animated: true)
}
if self.progress >= progress {
timer.invalidate()
if completion != nil {
completion!()
}
}
}
}
}
// Just call this extension with your UIProgressView like this
YOUR_PROGRESS_VIEW.setAnimatedProgress(duration: 100) { // Here 100 meaning 10 seconds
debugPrint("Done!")
}
Related
I am working on an app and I want to animate the numbers in my app. I know I need to use an NSTimer. Just not sure how. For example I want the app to count up from 0.00 to 176.20 (self.total.text).
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(update) userInfo:nil repeats:YES];
- (void)update{
float currentTime = [self.total.text floatValue];
float newTime = currentTime + 0.1;
self.total.text = [NSString stringWithFormat:#"%f", newTime];
}
You need to decide at what increment you want to count. You want to stop at 176.20 so it seems like an increment of 0.1 seconds would be what you want. You need a variable to store the current position.
Obj-c///
const float limit = 176.2f
#property (nonatomic) float seconds;
#property (nonatomic, strong) NSTimer *updateTimer;
// Initialize
self.seconds = 0.0f;
self.updateTimer = [NStimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(timerFired) userInfo:nil repeats:true];
Swift///
var seconds = 0.0
let limit = 176.2
let timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("timerFired"), userInfo: nil, repeats: true)
Then you need to create a function which is used to update the label every time the timer fires and a function which schedules the timer.
Obj-c///
- (void)timerFired {
self.seconds += 0.1f;
self.label.text = [NSString stringWithFormat:#"%f", self.seconds];
if (self.seconds >= limit) {
[self.updateTimer invalidate];
}
}
Swift///
func timerFired() {
seconds += 0.1 //Increment the seconds
label.text = "\(seconds)" //Set the label
if (seconds >= limit) {
timer.invalidate()
}
}
I want to use NSTimer as a Countdown. The counter works fine;-)!
But I I switch to another viewController the timer doesn't runs in "foreground" - so the label isn't updated.... after coming back to this view.
My NSLOG shows that the timer is still runnig, like I want ;-)
So in whicht way I have to work, that my timer update my label?
Here is the code:
- (IBAction)startClock:(id)sender {
globalTimer = 20;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(updateCircularProgressBar)
userInfo:nil
repeats:YES];
}
- (void)updateCircularProgressBar
{
// Values to be passed on to Circular Progress Bar
if (globalTimer > 0 && globalTimer <= 1200) {
globalTimer--;
minutesLeft = globalTimer / 60;
secondsLeft = globalTimer % 60;
[self drawCircularProgressBarWithMinutesLeft:minutesLeft secondsLeft:secondsLeft];
NSLog(#"Time left: %02d:%02d", minutesLeft, secondsLeft);
}
else {
[self drawCircularProgressBarWithMinutesLeft:0 secondsLeft:0];
[timer invalidate];
}
}
I tested to run the "updateCircularProgressBar" in my viewDidLoad but this shows NO result...
THX for Help
UPDATE more with more Code:
/*-------------------- TIMER --------------------*/
// Draws the progress circles on top of the already painted background
- (void)drawCircularProgressBarWithMinutesLeft:(NSInteger)minutes secondsLeft:(NSInteger)seconds
{
// Removing unused view to prevent them from stacking up
for (id subView in [self.view subviews]) {
if ([subView isKindOfClass:[CircularProgressTimer class]]) {
[subView removeFromSuperview];
}
}
// Init our view and set current circular progress bar value
CGRect progressBarFrame = CGRectMake(0, 0, 180, 180);
progressTimerView = [[CircularProgressTimer alloc] initWithFrame:progressBarFrame];
[progressTimerView setCenter:CGPointMake(160, 210)];
[progressTimerView setPercent:seconds];
if (minutes == 0 && seconds <= 0) {
[progressTimerView setInstanceColor:[UIColor magentaColor]];
}
// Here, setting the minutes left before adding it to the parent view
[progressTimerView setMinutesLeft:minutesLeft];
[progressTimerView setSecondsLeft:secondsLeft];
[self.view addSubview:progressTimerView];
progressTimerView = nil;
}
The label is in another file (CircularProgressTimer) which controls the progessbar...
I am trying to make a game movement animation in objective c so that when a button is pressed something will move across the screen while it is pressed. This works fine though the calling of the NSTimer which I am using is irregular and I am getting laggy movements. This is in iOS 6 so I wont use sprite kit as it is not available
Any suggestions on how to make it a regular call or to make it a smooth animation would be much appreciated
Thanks in advance
Here is the code:
-(void) click {
if (!self.animating) {
self.animating = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:#selector(move)
userInfo:nil
repeats:YES];
}
}
- (void) cancelClick {
self.animating = NO;
[timer invalidate];
}
-(void) move {
CGPoint origin = self.target.frame.origin;
if ([self.direction isEqual:#"left"]) {
origin.x -= self.magnitude;
} else if ([self.direction isEqual:#"right"]) {
origin.x += _magnitude;
} else if ([self.direction isEqual:#"up"]) {
origin.y -= _magnitude;
} else {
origin.y += _magnitude;
}
[self.target move:0 toPoint:origin animated:YES delay:0 animationOptions:UIViewAnimationOptionCurveLinear];
}
I am trying atm doing a game. I got some problems with the RandomPositioning with the blocks. With my code, the Blocks keep spawning at the same lane very fast. But thats not what I mean to. They should appear like a Mario Game. My Code:
HumanMovement = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(HumanMoving) userInfo:nil repeats:YES];
[self PlaceBlocks];
BlockMovement = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(BlockMoving) userInfo:nil repeats:YES];
}
-(void)BlockMoving{
StartingBlock.center = CGPointMake(StartingBlock.center.x -1, StartingBlock.center.y);
Block1.center = CGPointMake(Block1.center.x -1, Block1.center.y);
Block2.center = CGPointMake(Block2.center.x -1, Block2.center.y);
if ( Block1.center.x > 20) {
[self PlaceBlocks];
}
}
-(void)PlaceBlocks{
RandomBlock1Position = arc4random() %568;
RandomBlock1Position = RandomBlock1Position + 140;
RandomBlock2Position = RandomBlock2Position + 500;
Block1.center = CGPointMake(193 , RandomBlock1Position);
Block2.center = CGPointMake(280 , RandomBlock2Position);
}
So if i understood correctly your blocks should respawn once the reach the left side. In order to do so you have to change your center check position to :
if ( Block1.center.x < 20) {
[self PlaceBlocks];
}
Hey guys I'm extremely new to programming and especially with Objective C so please bear with me. I been practicing my skills on an iPhone app project I have been working on and now am stuck on an issue with saving time. I have a simple slider puzzle game that has a timer that increases until you finish the puzzle. the time is represent in this format "00:00". i would like to be able to save the lowest time after completion and present it on the screen on the start of the app for reference on the time to beat. The problem I face however is that it keeps saving the time 0 as the lowest and nothing can beat that.
Below is code of my:
Timer
-(void)setTimer
{
self.secondsCount = 0;
self.gameCountDownTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerRun) userInfo:nil repeats:YES];
}
-(void)timerRun
{
self.secondsCount++;
NSString *timerOutput = [NSString stringWithFormat:#" %02.f : %02i", round(self.secondsCount / 60), self.secondsCount % 60 ];
self.timeLabel.text = timerOutput;
}
StartGame Button
- (IBAction)start:(id)sender {
// reset steps
self.secondsCount=0;
step = 0;
[self setTimer];
// set the view so that it can interact with touches
[board setUserInteractionEnabled:YES];
// set the label text to 'reset'
[startButton setTitle:#"Reset" forState:UIControlStateNormal];
// initialize the board, lets play!
[board playWithImage:image andSize:(boardSize.selectedSegmentIndex+3)];
}
End of Game
(void)puzzleBoardDidFinished:(PuzzleGameView *)puzzleBoard {
// add the full image with 0.0 alpha in view
if(self.secondsCount!=0){
self.finalTime = self.secondsCount;
NSLog(#"seconds is: %i",self.secondsCount);
[self saveTime];
if(self.finalTime<self.bestTime) {
NSLog(#"bestTime! is: %i",self.finalTime);
[self saveTime];
}
}
[self.gameCountDownTimer invalidate];
self.gameCountDownTimer = nil;
UIImageView *fullImage = [[UIImageView alloc]initWithImage:image];
fullImage.frame = board.bounds;
fullImage.alpha = 0.0;
[board addSubview:fullImage];
[UIView animateWithDuration:.4
animations:^{
// set the alpha of full image to 1.0
fullImage.alpha = 1.0;
}
completion:^(BOOL finished){
// set the view interaction and set the label text
NSLog(#"Congrats! You finish this %d x %d puzzle with %d steps", (boardSize.selectedSegmentIndex+3), (boardSize.selectedSegmentIndex+3), step);
[board setUserInteractionEnabled:NO];
[startButton setTitle:#"Start" forState:UIControlStateNormal];
}];
}
And Attempt to save the data
-(void)saveTime {
[[NSUserDefaults standardUserDefaults]setInteger:self.secondsCount forKey:#"BestTime"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
This was in my viewdidload
self.bestTime = [[NSUserDefaults standardUserDefaults]integerForKey:#"BestTime"];
self.bestTimeLabel.text = [NSString stringWithFormat:#" %02.f : %02i", round(self.bestTime / 60), self.bestTime % 60 ];
As stated before Im pretty new so any advice and recommendations would be awesome. Im definitely eager to learn more about this stuff and would greatly appreciate if you guys could help with the journey. Thank You
It looks like [[NSUserDefaults standardUserDefaults]integerForKey:#"BestTime"] is 0 every time you assign its value to self.bestTime.
This code might help:
if(self.bestTime == 0){
self.bestTime = finalTime;
}
Your code looks ok. I'm pretty sure it's just the showing the value in NSLog that is not working.
Change:
self.bestTimeLabel.text = [NSString stringWithFormat:#" %02.f : %02i", round(self.bestTime / 60), self.bestTime % 60 ];
To:
self.bestTimeLabel.text = [NSString stringWithFormat:#" %02.f : %02i", round(self.bestTime / 60.0f), self.bestTime % 60 ];
For float variable: int / int yields integer which you are assigning to float and printing it so it's 0.00.