Repeating animations using the Stop Selector - iphone

I'm trying to repeat an animation until a certain condition is met. Something like this:
- (void) animateUpdate {
if (inUpdate) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: #selector(animateUpdate)];
button.transform = CGAffineTransformMakeRotation( M_PI );
[UIView commitAnimations];
}
}
This will run the first time, but it won't repeat. The selector will just be called until the application crashes.
How should I do this?
Thanks.

Same issue. Here is some code that does the same thing
- (void)beginRotation{
[UIView beginAnimations:#"ghostRotate" context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:5.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
ghostImage.transform = CGAffineTransformMakeRotation(M_PI*0.5);
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
if ([finished boolValue]){
[self beginRotation];
}
}
When the first animation completes, it calls the didStop... This calls the beginAnimation method again which returns immediately to the didStop again. finished is set to 1 and it enters a stack overflow condition...
thoughts?

Core Animation works asynchronously, that is, your code does not block the thread and the animation actually starts at the next pass of the run loop. In order to repeat an animation you should restart it in your animation-did-stop selector or explicitly use CAAnimation's repeatCount, depending on your needs. Otherwise Core Animation will coalesce all your animations into one.

Related

Repeat beginAnimations -- All Animations

I'm making a simple image rotator by fading in and out 4 different images. It works great, until the end, when I want all four animations to repeat.
I've tried the repeat count, but that will only apply to that one specific animation. How do I create an entire loop?
My code is below. Thanks in advance!
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:slideshow cache:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:3];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationDelay:3];
imageOne.alpha = 0;
imageTwo.alpha = 1;
[UIView setAnimationDelay:6];
imageTwo.alpha = 0;
imageThree.alpha = 1;
[UIView setAnimationDelay:9];
imageThree.alpha = 0;
imageFour.alpha = 1;
[UIView commitAnimations];
You can start by putting a name to your animations so instead of beginAnimations:nil, you'd put beginAnimations: #"Button Animations" or something like that. Also, you should set the delegate of the animation to self. This can be done by adding the following line of code into your animation block:
[UIView setAnimationDelegate: self];
Then you can put this whole entire animation block into a class method of it's own (in your view controller). Lets call it doAnimation. This is just for safe measure. the next thing you should do is implement this delegate function in your view controller:
-(void) animationDidStop: (NSString *) animationID finished:(NSNumber *)finished context:(void *)context{
if([animationID isEqualToString:#"Button Animation"]){
[self doAnimation];
}
}
So pretty much this will ensure that your animations will repeat. If this method doesn't work, let me know, I didn't test it. But I think it'll work.

animations on infinite loop

I have 5 different animations that animate then disappear one after another. Is there a way to put them on an infinite loop so animation #1 begins and ends, then anim #2 begins and ends etc..? the whole process then would repeat on an infinite loop.
I have the animations in separate blocks on delays. I'm guessing that there is a better way of doing this. this is what I have at the moment:
-(void) firstAnimation {
[UIView beginAnimations:#"Fade Out Image" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDelay:40];
[UIView setAnimationRepeatCount:30];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
theImage.alpha = 1;
theImage.alpha = 0.1;
[UIView commitAnimations];
[self secondAnimation];
}
-(void) secondAnimation {
tapImage2.hidden = NO;
[UIView beginAnimations:#"Fade Out Image" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDelay:53];
[UIView setAnimationRepeatCount:29];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
theImage2.alpha = 1;
theImage2.alpha = 0.1;
[UIView commitAnimations];
[self thirdAnimation];
}
this then goes on for 5 animations. thanks for any help.
Instead of using the delay, set the animation delegate and create an animation done method. I notice you are already setting the delegate.
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context {
//Start next animation based on the animationID of the last one...
}

How to make a line of code execute only after the time interval of the animation block?

I have put a line of code inside the UIAnimation block. And the next line comes after the animation block. I want the second line only to be executed after the time interval of the first animation block.
Eg:-
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.5];
//First line comes here
[self.view addSubview:subView];
[UIView commitAnimations];
Then the 2nd line
[subView2 removeFromSuperView];
I want the 2nd line only to be executed after the 0.5 second interval of the animation action. Is it possible to do like this?
You can set a delegate for animation and remove subview in its method:
...
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[UIView setAnimationDelegate:self];
//First line comes here
[self.view addSubview:subView];
[UIView commitAnimations];
...
Then in delegate's animation did stop handler remove your 2nd subview:
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
if ([finished boolValue])
[subView2 removeFromSuperview];
}

Triggering other animation after first ending Animation (Objective-C)

I have a simple animation which simply modify the position of a button:
[UIView beginAnimation:nil context:nil];
[UIView setAnimationsDuration:3.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
mybutton.frame = CGREctMake(20, 233, 280, 46);
[UIView commitAnimations];
I want to perform some other animations when this one is finish, how to do that?
You could look at setAnimationBeginsFromCurrentState:. All the animations are run in their own threads, so [UIView commitAnimations] is a nonblocking call. So, if you begin another animation immediately after committing the first one, after appropriately setting whether or not it begins from the current state, I think you'll get the behavior you want. To wit:
[UIView beginAnimation:nil context:nil];
// set up the first animation
[UIView commitAnimations];
[UIView beginAnimation:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:NO];
// set up the second animation
[UIView commitAnimations];
Alternately, you could provide a callback by doing something like
[UIView beginAnimation:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)
// set up the first animation
[UIView commitAnimations];
//...
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
// set up the second animation here
}
a code segment for getting start.. setup initial (the first) animation:
- (void) aniPath:(AnimationPath *) path
{
[UIView beginAnimations:path->aniname context:path];
[UIView setAnimationDuration:path->interval];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(aniDone:finished:context:)];
// your initial animation
[UIView commitAnimations];
}
chains to another animation when the first is done:
- (void) aniDone:(NSString *) aniname finished:(BOOL) finished context:(void *) context
{
AnimationPath *path = (AnimationPath *) context;
if ([aniname isEqualToString:path->aniname]) {
[UIView beginAnimations:path->aniname context:context];
[UIView setAnimationDuration:path->interval];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(aniDone:finished:context:)];
// more animations, even recursively
[UIView commitAnimations];
}
}
Use the +[UIVIew setAnimationDelegate:] and +[UIView setAnimationDidStopSelector:] methods to configure your class to receive a message when the animation ends.
it quite easier.
you can just
- (void)animationDidContiune:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIView *currentObj = context;
[self callTheAnimation: currentObj];
}
you can easily loop the animation.
To end it - I would create an animationDidEnded and use it instead of animationDidContiune
once you want to stop it (like simple if in animation that chooses either to contiune or end).
HF.
AND WHAT's IMPORTANT:
use this type of animating meths:
- (void)callTheAnimation:(UIView*)itemView
{
[UIView beginAnimations:#"animation" context:itemView];
.
.
.
}
they are quite flexible - you can animate whatever here due to hierarchy of the objects.

How can I use this animation code?

I'm a newbie and I need some help.
I want to display a popup image over a given UIView, but I would like it to behave like the UIAlertView or like the Facebook Connect for iPhone modal popup window, in that it has a bouncy, rubbber-band-like animation to it.
I found some code on the net from someone who was trying to do something similar. He/she put this together, but there was no demo or instructions.
Being that I am so new, I don't have any idea as to how to incorporate this into my code.
This is the routine where I need the bouncy image to appear:
- (void) showProductDetail
{
. . .
////////////////////////////////////////////////////////////////////////
// THIS IS A STRAIGHT SCALE ANIMATION RIGHT NOW. I WANT TO REPLACE THIS
// WITH A BOUNCY RUBBER-BAND ANIMATION
_productDetail.transform = CGAffineTransformMakeScale(0.1,0.1);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
_productDetail.transform = CGAffineTransformMakeScale(1,1);
[UIView commitAnimations];
}
. . .
}
This is the code I found:
float pulsesteps[3] = { 0.2, 1/15., 1/7.5 };
- (void) pulse {
self.transform = CGAffineTransformMakeScale(0.6, 0.6);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:pulsesteps[0]];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(pulseGrowAnimationDidStop:finished:context:)];
self.transform = CGAffineTransformMakeScale(1.1, 1.1);
[UIView commitAnimations];
}
- (void)pulseGrowAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:pulsesteps[1]];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(pulseShrinkAnimationDidStop:finished:context:)];
self.transform = CGAffineTransformMakeScale(0.9, 0.9);
[UIView commitAnimations];
}
- (void)pulseShrinkAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:pulsesteps[2]];
self.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
Thanks in advance for any help that you can give me.
It's pretty simple. In your showProductDetail method, you start an animation block, then set the _productDetail.transform property, and then commit the block. This is what makes the animation happen.
The code that you found is designed to do a chain of such animations, but the property being modified is on self instead of on _productDetail. If _productDetail is an instance of a class that you created yourself, you can put the animation code inside that class.
Otherwise, just move the code inside the pulse method to the showProductDetail method, and put the two other methods below that method. Replace self.transformwith _productDetail.transformin all three methods.