Cocoa setAnimationDidStopSelector - iphone

Currently I have this code that works fine
[UIView setAnimationDidStopSelector:#selector(animationDone:finished:context:)];
- (void)animationDone:(NSString *)animationID finished:(BOOL)finished context:(void *)context {
// do stuff here
}
Logging the value of animationID gives me a null.
How can I pass value to the #selector?
I tried
[UIView setAnimationDidStopSelector:#selector(animationDone:#"animation1"finished:context:)];
That gives me an error.
Thanks,
Tee

The string passed to the selector is the one you use in this method call:
[UIView beginAnimations:#"your_animation_name_here" context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
// whatever changes here
[UIView commitAnimations];
Afterwards, you can do this:
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
if ([animationID isEqualToString:#"your_animation_name_here"])
{
// something done after the animation
}
}

Related

Repeating animations using the Stop Selector

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.

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.

Do something when animation is ready.

I have a animation in my navigationbased application.
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:self.view cache:YES];
[UIImageView commitAnimations];
Directly after this bit of code i call
[self.navigationController popViewControllerAnimated:NO];
The thing is, I don't want to pop my ViewController before my animation is ready.
Set animations delegate and didStop selector and pop your view controller in that didStop method you specify:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:self.view cache:YES];
[UIImageView commitAnimations];
Note, that didStop selector must be of the form specified in docs (see + setAnimationDidStopSelector method in docs for more details):
selector should be of the form: -
(void)animationDidStop:(NSString
*)animationID finished:(NSNumber *)finished context:(void *)context.
You can set a selector to be called when the animation is finished:
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:finished:context:)];
And in that selector call the pop the view controller.
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
// Pop the controller now
}

FadeOut/FadeIn transition for label text change

I'm trying to change the text of an UILabel with a little transition (fade out, change text, fade in) but I'm facing some problems. Here is my code:
- (void) setTextWithFade:(NSString *)text {
[self setAlpha:1];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.25];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(fadeDidStop:finished:context:)];
[self setAlpha:0];
[UIView commitAnimations];
}
- (void)fadeDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.25];
[self setAlpha:1];
[UIView commitAnimations];
}
This code "works" (the effect is working well), but what I can't figure out is how to change the label text in the "fadeDidStop" function... How can I "pass" the text variable from my first function to the second?
Thanks in advance
You pass the text in the context:
[UIView beginAnimations:nil context:text];
Then in your fadeDidStop method:
NSString *text = (NSString*) context;
Be mindful when passing objects in the context, make sure they are retained properly.
...
[UIView beginAnimations:nil context:[text retain]];
...
- (void)fadeDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
self.text = (NSStrinhg *)context;
[context release];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.25];
[self setAlpha:1];
[UIView commitAnimations];
}
maybe the simpliest way is to declare NSString object in your .h file and use it to store text to change.