Objective C - Animation Blocks, multiparameters - iphone

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.

Related

iPhone: Wait until UIView animation is Finished

I'm creating a turn based game for the iPhone that contains animations between turns, and I want to wait on the [UIView animateWithDuration:...] method call inline in code. Is there a way to make this call synchronously instead of asynchronously? Currently what I am doing is...
// Some code...
NSConditionLock *conditionLock = [[NSConditionLock alloc] initWithCondition:0];
dispatch_sync(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1
animations:^{
// some animation
}
completion:^(BOOL finished){
[conditionLock lock];
[conditionLock unlockWithCondition:1];
}];
});
// forces thread to wait until completion block is called
[conditionLock lockWhenCondition:1];
// More code...
Therefore in the above code, "// More code..." is only reached after the animation has completely finished. Obviously this code must run on a secondary thread, and it works as I want to. However, I have a feeling that using an NSConditionLock in combination with gcd is bad form and blocking the secondary thread in this way is not optimal for performance. Is my current code alright, or is there a better way to do this? Thanks.
Edit:
The key point is that "// more code..." is inline, and not in the completion block.
Really what I want to know, is it alright to use NSConditionLock's in combination with GCD, and if not what's the better way?
I would just put "//More code" in another method and call that method in the completion block. This will ensure that your code is only fired once your animation completes.

Implicit conversion from enumeration type 'UIViewAnimationCurve' to different enumeration type 'UIViewAnimationTransition'

I'm getting some warnings when I use this line of code.
[UIView setAnimationTransition:UIViewAnimationCurveEaseInOut forView:nil cache:YES];
then i am getting some warning this is following
Implicit conversion from enumeration type UIViewAnimationCurve to
different enumeration type UIViewAnimationTransition
So please suggest to me how to resolve this problem in iOS 5.0.
UIViewAnimationCurveEaseInOut is not transition type for uiview animation transition, It's the type of animation curve. Following are the valid transition as per apple developer reference.
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown.
Please use one of them. If you want to set animation curve then do the following.
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

Keeping a Core Animation transition persistent?

I have a custom UILabel that I want to add a transition to when the text changes.
I create a transition:
CATransition *a = [CATransition animation];
a.duration = 1.0;
a.type = kCATransitionPush;
self.transition = a;
I set the transition to a property in my class. Here's the method I call to update the text:
- (void)postMessage:(NSString *)message {
[self.messageLabel.layer addAnimation:self.transition forKey:#"statusAnimation"];
self.messageLabel.text = message;
}
This all works fine. However, I don't want to keep adding the animation to my label. That slows it down every time I update.
My question is - how can I keep this transition persistent so it shows an animation every single time I call this method without having to add it manually every time?
What you're asking isn't quite possible. Core Animation is a stateful library, and copies the animation object you present, then releases it upon completion. If you are having issues with performance, you should be using the animation block methods. This overview of Core Animation with blocks should help you get started.

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 ...

I need help with Animation Callbacks (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.