I need help with Animation Callbacks (iPhone) - iphone

I am creating an application in iPhone and I have several UIViews and layers in it. I am doing some animations using CAKeyframeAnimation class and since the animations have to be chained, I have overridden the animationDidStop method in UIView.
I am getting the callbacks properly, however I just couldn't figure out how I can find which animation was ended so that I can start the next one. Only parameters to the callback function is a CAAnimation object and a boolean.
I can workaround this problem by setting a property in the class and using an enum for the various animations I use. However I just wanted to know if there is any built in attributes in the callbacks which I can set in the CAKeyframeAnimation object and then refer the same in the callback.
Any help would be greatly appreciated!

You can specify a name for an animation and read it in your delegate method.
[animation setValue:"firstAnimation" forKey:#"name"];
...
- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
if([[animation valueForKey:#"name"] isEqual:#"firstAnimation"] && finished) {
...
}
}

I know that you said that you're using CAKeyframeAnimations, but if you want simple animation of UIView properties (origin, bounds, alpha, etc.), you can wrap the change of the property or properties in a begin / commit block and specify a delegate method that is called upon completion of the animation. As long as the delegate method takes three arguments, you can call it whatever you want. For example:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:ANIMATIONDURATIONINSECONDS];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(yourAnimationHasFinished:finished:context:)];
// Change property or properties here
[UIView commitAnimations];
will cause the method
- (void)yourAnimationHasFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context;
to be called. The arbitrary naming this allows would provide you with a means of separating handling for the completion of different animations. I prefer this for simple animations.
For dealing with more complex animations that interact directly with CALayers, the animationDidStop:finished: delegate method does return the animation object that has finished. If you are making one instance that is the delegate for multiple animations, you could create an NSMutableDictionary of animations and NSNumbers for use in a switch statement within the animationDidStop:finished: method. As you create the CAKeyframeAnimation, use setObject:forKey: to assign it to its matching number, then use objectForKey: to find the number that corresponds to that animation in the completion method and feed that into a switch statement.

Related

Pointer to Pointer in Objective-C

I'm trying to learn to play with pointers here.
I have a UIImageView. I need to point its image property to another UIImageViews image property, so that whenever I change the second UIImageViews image, the first one gets updated automatically.
Some pointer manipulation here but I can't seem to get my head around it.
That is impossible. They are just pointers. For example aImageView and bImageView. You can set them's image pointer to point to the same UIImage. But change one of them does NOT change the other.
Maybe you can consider to use KVO to do what you want to do. Change one then your method will be called. Then in your method you can change the other.
you can use Key-Value Observing
from Apple Docs
Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects.
KVO’s primary benefit is that you don’t have to implement your own scheme to send notifications every time a property changes.
[imageView1 addObserver:self
forKeyPath:#"image"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:NULL];
- (void) observeValueForKeyPath:(NSString *)path ofObject:(id) object change:(NSDictionary *) change context:(void *)context
{
// this method is used for all observations, so you need to make sure
// you are responding to the right one.
}
Try to override the setter. Make a subclass of UIImageView, have a property for second UIImageView and write something like
-(void)setImage:(UIImage*)image{
_image = image;
self.secondImageView.image = image;
}
Hope this helps.

What can be passed in (void *)context?

I'm doing some UIView animation stuff using
[UIView beginAnimations:nil context:nil];
// ... Animation configuration ...
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationEnded:finished:context:)];
[UIView commitAnimations];
Regarding the following question: Apple rejected app because of animationDidStop:finished:context: is a non-public api
I implemented my own method as the "setAnimationDidStopSelector".
My question is regarding the context:(void *)context parameter. Apple defines it as follow :
Additional application-supplied
information that is passed to the
animation delegate messages—the
selectors set using the
setAnimationWillStartSelector: and
setAnimationDidStopSelector: methods.
I'm wondering what king of thing can be passed in as a context. I'm relatively new to Objective-C and C programming and a bit lost with the void* type.
Can we pass in any sort of argument, objects, NSDictionnary, NSString, etc.
Thanks
void * is a pointer to anything. You can pass a pointer to any object or to other stuff such as a struct or a Core Foundation opaque type. To get rid of the compiler warning, cast the pointer to void *:
... context:(void *)myDictionary];
Be aware that the method has no idea what context contains and thus will not retain it or otherwise care for correct memory managemnet. You have to ensure that the thing you pass to context still exists when the animation delegate methods are called.
context:(void *)myDictionary];
When calling this method and trying to pass
(void *)[NSNumber numberWithInt:5] -
xCode proposes to make some _bridge because of invalid pointerCast from C to Objective-C ...

Objective-C's UIView and animationIDs

What are all the valid animationID strings for the beginAnimations:: class method on UIView?
The animationID is any string you decide to use. It's for identifying the animation in the animations's willStart and didStop delegate methods.
From the documentation:
animationID Application-supplied
identifier for the animations within a
block that is passed to the animation
delegate messages—the selectors set
using the
setAnimationWillStartSelector: and
setAnimationDidStopSelector: methods.

Objective C - Animation Blocks, multiparameters

I have a question... how is programmatically reached the Animation blocks?
[UIView beginAnimations:#"repositionAnimation" context:nil];
// -----------------------------------------------------------------------------
[view setFrame:viewRect];
[view setAlpha:0];
...
...
// -----------------------------------------------------------------------------
[UIView commitAnimations];
How the messages are stored and processed on commitAnimations ???
I just guess that the begin function invokes some kind of holder for messages, storing the messages somehow and process them in loop ?
is there a way to work with a messages some kind like in argument lists???
You are using the animation proxy when you call [UIView beginAnimations:context:]. If you want to manage animations explicitly, use Core Animation. You can monitor progress of a view's layer by periodically (using a timer) checking the layer's presentationLayer.

What are the two options that come with the core animations beginAnnimations method?

I was wondering what they mean by:
[CustomView beginAnimations:#"whatIsThis" context:whatIsThis];
I am just wondering what those who things do and how I would use them?
Please help!
They are basically application-specific helper objects. animationID is used to distinguish between the different animations (that could be happening around the same time). context is additional object that gets passed to the delegates and listeners of the animation status. Both are optional, and passing nil should work.
From documentation:
animationID
Application-supplied identifier for the animations within a block that is passed to the animation delegate messages—the selectors set using the setAnimationWillStartSelector: and setAnimationDidStopSelector: methods.
context
Additional application-supplied information that is passed to the animation delegate messages—the selectors set using the setAnimationWillStartSelector: and setAnimationDidStopSelector: methods.