I have a simple explosion animation that works just fine in any method in my class. However I want to call it once the timer runs out, from the timer update method. The problem is it will not work from here for whatever reason (something to do with the timer surely). It simply unhides my image.. no animation. I cannot figure out how to get it to work.
- (void)explosionAnimation
{
imgExplosion.hidden=FALSE;
//set starting point of explosion
CGRect explosionFrame = self.imgExplosion.frame;
explosionFrame.origin.x = explosionFrame.origin.y = -960.0f;
explosionFrame.size.width = explosionFrame.size.height = 1920.0f;
[UIView animateWithDuration:1.5f animations:^{
self.imgExplosion.frame = explosionFrame;
} completion:^(BOOL finished) {
self.imgExplosion.hidden = YES;
}];
}
-(void) createTimer
{
// Create timer instance
if (timer != nil){
[timer invalidate];
hasTimerStarted = NO;
}
// Initialize the timer.
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerUpdater)
userInfo:nil repeats:YES];
}
- (void)timerUpdater{
if(!hasTimerStarted){
intTotalSeconds = [strTotalNumberofSeconds intValue];
hasTimerStarted = YES;
}
else{
intTotalSeconds--;
self.lblTimer.text = [self revertTimeToString:intTotalSeconds];
}
// if totalSeconds hits zero, then time is up! You lose!
if (intTotalSeconds == 0){
[timer invalidate];
[self explosionAnimation];
hasTimerStarted = NO;
[self addPlayAgainButton];
}
}
Try putting some delay or call explosion method on Main Thread like
[self performSelector:#Selector(explosionAnimation) withObject:nil afterDelay:1.0];
Related
I try to create a UITexView with auto scrolling when press button start. And have a button stop, when pressed it will stop scrolling. Pressing button start again and it will continues to scroll down. How to handle this function.
I have research some code that this code below work with me.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"%f %f",_txvSentence.contentSize.width , _txvSentence.contentSize.height);
if (scrollingTimer == nil) {
scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:(35.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
NSLog(#"%#",scrollingTimer);
}
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
CGPoint scrollPoint = self.txvSentence.contentOffset;
//scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1);
scrollPoint = _txvSentence.contentOffset;
scrollPoint.y= scrollPoint.y+1;
[_txvSentence setContentOffset:scrollPoint animated:NO];
//[self.txvSentence setContentOffset:scrollPoint animated:NO];
}
But i cannot stop this animation. And how to set dynamic duration such as when come to the end of text it automatically stop.
Sorry because my bad english. If not understand please tell me where I will explain it clearly.
Try this:
self.scrollView.scrollEnabled = NO;
CGFloat scrollHeight = 100;
//===
- (void) spinWithOptions: (UIViewAnimationOptions) options {
// this spin completes 360 degrees every 2 seconds
[UIView animateWithDuration:10
delay:0
options:options
animations:^{
self.scrollView.contentOffset = CGPointMake(0, scrollHeight);
}
completion:^(BOOL finished) {
if (finished) {
if (animating) {
// if flag still set, keep spinning with constant speed
[self spinWithOptions: UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction];
} else if (options != UIViewAnimationOptionCurveEaseOut) {
// one last spin, with deceleration
[self spinWithOptions: UIViewAnimationOptionCurveEaseOut];
}
}
}];
}
- (void) startAnimating {
if (!animating) {
animating = YES;
[self spinWithOptions: UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction];
}
}
- (void) stopAnimating {
// set the flag to stop spinning after one last 90 degree increment
animating = NO;
}
You can use NSTimer.
// Global var
CGFloat scrollHeight = MAX_HEIGHT;
CGFloat currentOffsetY = 0.0f;
NSTimer *timer;
self.timer = [NSTimer scheduledTimerWithTimeInterval:YOUR_TIME_INTERVAL target:self selector:#selector(scrollText:) userInfo:nil repeats:YES];
- (void)scrollText:(NSTimer *)timer {
currentOffsetY++;
if (currentOffsetY >= MAX_HEIGHT) {
[self.timer invalide];
}
self.scrollView.contentOffset = CGPointMake(0, currentOffsetY);
}
// Your button action
- (void)stopAnimation:(UIButton *)button {
[self.timer invalide];
}
I have a requirment of 15sec timer in my app in the circular progress bar sort of animation which will contain label in the center of seconds remain
Following code gives the labelprogress from 0.0 to 1.0f but I want to map it to 15 seconds countdown with the smooth animation also if there is timer extender than it should get the time added with the smooth animation
ex: Firstly I need to start from 15 seconds and if user clicks on the timeextender powerup and current time is the 10sec then it should be 25 sec and acoordingly the progressbar percentage should work.
So what logic I need to map to get the above requirement done
- (void)progressChange
{
// Labeled progress views
NSArray *labeledProgressViews = #[//self.labeledProgressView,
self.labeledLargeProgressView];
for (DALabeledCircularProgressView *labeledProgressView in labeledProgressViews) {
CGFloat progress = ![self.timer isValid] ? self.stepper.value / 10.0f : labeledProgressView.progress + 0.01f;
[labeledProgressView setProgress:progress animated:YES];
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%.2f", labeledProgressView.progress];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.03
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
- (void)stopAnimation
{
[self.timer invalidate];
self.timer = nil;
self.continuousSwitch.on = NO;
}
- (IBAction)TimeExtender:(id)sender
{
if (labeledProgressView.progress >= 1.0f && [self.timer isValid]) {
[labeledProgressView setProgress:0.f animated:YES];
}
}
I solved it by myself here's the code
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
}
else{
progress=labeledProgressView.progress + 0.06666667f;
[labeledProgressView setProgress:progress animated:YES];
seconds --;
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
I am using NSTimer and circular progress bar for the countdown timer i.e 15seconds
Its working with the following code but I am getting tick animation for the progress bar and not the smooth one, how to make it smooth animation
- (void)viewDidLoad
{
[super viewDidLoad];
self.labeledLargeProgressView.roundedCorners = NO;
self.labeledLargeProgressView.trackTintColor =[UIColor colorWithRed:0.0f/255.0f green:173.0f/255.0f blue:255.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.progressTintColor =[UIColor colorWithRed:255.0f/255.0f green:96.0f/255.0f blue:88.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.thicknessRatio = 1.0f;
self.labeledLargeProgressView.clockwiseProgress = YES;
[self.view addSubview:self.labeledLargeProgressView];
seconds = 15.0;
[self startAnimation];
}
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
}
else{
progress=labeledProgressView.progress + 0.06666667f;
[labeledProgressView setProgress:progress animated:YES];
seconds --;
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
- (void)stopAnimation
{
[self.timer invalidate];
self.timer = nil;
self.continuousSwitch.on = NO;
}
What i found out is a set of both UIview animations and progress view animatons that work much nicer and animate the progressview smoothly. If you just use the combination of animation and progressview animation it is fired directly without regard to the UIview animation timer.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0f
target: self
selector: #selector(updateTimer)
userInfo: nil
repeats: YES];
}
- (void)updateTimer
{
if (progressView.progress >= 1.0) {
[timer invalidate];
}
[UIView animateWithDuration:1 animations:^{
float newProgress = [self.progressView progress] + 0.125;
[self.progressView setProgress:newProgress animated:YES];
}];
}
Feel free to adjust the animation times to even better and smooth transitions
I solved it by myself what I did is I am updating more frequently 0.1f instead of 1.0f
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
_counter = 0;
}
else{
progress=labeledProgressView.progress + 0.00666667f;
_counter ++;
[labeledProgressView setProgress:progress animated:YES];
if(_counter % 10 == 0){
seconds --;
}
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
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.
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.