Why addAnimation:forKey not working in viewDidLoaded - ios

I have the following method called by viewDidLoad. This method is to create a CALayer to show a image. This layer has a mask whose path is a UIBezierPath created by my private method. I want the mask to rotate infinitely, and then I add a CABasicAnimation object to the mask.
- (void) createPathLmask
{
// mask layer
self.pathLayer = [CALayer layer];
self.pathLayer.bounds = CGRectMake(0.0, 0.0, 120, 120);
CGPoint position = self.view.layer.position;
position.y += 140;
self.pathLayer.position = position;
self.pathLayer.backgroundColor = [UIColor redColor].CGColor;
UIImage *backimage = [UIImage imageNamed:#"image2"];
self.pathLayer.contents = (__bridge id)backimage.CGImage;
self.pathLayer.contentsGravity = kCAGravityResizeAspectFill;
// mask
CAShapeLayer *mask = [CAShapeLayer layer];
mask.bounds = CGRectMake(0.0, 0.0, 120, 120);
mask.position = CGPointMake(60.0f, 60.0f);
mask.contentsGravity = kCAGravityResizeAspectFill;
mask.path = [self createBezierPathInRect:mask.bounds].CGPath;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// rotate the mask repeatedly
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = #"transform.rotation";
animation.duration = 4.0f;
animation.byValue = #(M_PI * 2);
animation.repeatCount = HUGE_VALF;
[mask addAnimation:animation forKey:#"rotation_repeatedly"];
});
self.pathLayer.mask = mask;
[self.view.layer addSublayer:self.pathLayer ];
}
I find that the rotation animation can only work when I put the addAnimation:forKey into the dispatch_after block with 1 second delay. If those codes are moved out of the block, the mask will not rotate.
So there must be something not ready when animation is added to the layer in viewDidLoaded. I am wondering what is not ready yet? Is there any document or explanation about the suitable chance to add the animation?

So there must be something not ready when animation is added to the layer in viewDidLoaded
Correct. This is way too early for animation. Keep in mind that the view at this point merely exists and that's all; it isn't even part of the interface. You cannot animate a view that isn't part of the view hierarchy. There is nothing, at this point, to animate.
The view first becomes part of the interface between the first call to viewWillAppear and the first call to viewDidAppear. That is what "appear" means (as opposed to what "loaded") means.

There's great documentation on Apple's site here. Putting in simply though:
ViewWillAppear - This method is called before the view controller's view is about to be added to a view hierarchy and before any animations are configured for showing the view. You can override this method to perform custom tasks associated with displaying the view. For example, you might use this method to change the orientation or style of the status bar to coordinate with the orientation or style of the view being presented.

Related

CABasicAnimation appears offscreen by some margin

So I am trying CABasicAnimation for the very first time. I am trying to apply it on a layer and I want layer to interpolate from one point to another. I initially set a negative x coordinate and I put the animation on the infinite. It is working but then it takes few seconds to appear on screen. So it should completely go to the end and start again. Following is code
[[self bgImageView] setImage:[UIImage imageNamed:#"bg_dynamicwx_cloudyday_3.jpg"]];
for (CALayer *layer in self.emitterView.layer.sublayers) {
[layer removeAllAnimations];
}
[self.emitterView.layer removeAllAnimations];
NSArray *subLayers = self.emitterView.layer.sublayers;
for (CALayer *layer in subLayers) {
[layer removeFromSuperlayer];
}
CALayer *mask = [CALayer layer];
UIImage *layerImg = [UIImage imageNamed:#"2_cloud.png"];
mask.bounds = CGRectMake(self.emitterView.bounds.origin.x, self.emitterView.bounds.origin.y, layerImg.size.width, layerImg.size.height);
mask.contents = (id)layerImg.CGImage;
CGPoint fromPoint = CGPointMake(-layerImg.size.width, 0);
CGPoint toPoint = CGPointMake(layerImg.size.width, 0);
mask.position = fromPoint; // CoreAnimation animations do *not* persist
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.fromValue = [NSValue valueWithCGPoint:fromPoint];
animation.toValue = [NSValue valueWithCGPoint:toPoint];
animation.duration = 150;
animation.repeatCount = INFINITY;
[mask addAnimation:animation forKey:#"position"];
[self.emitterView.layer addSublayer:mask];
Basically I'm trying the cloud animation, where the cloud is floating over the screen. I'm pretty sure I got some concept wrong here for basic animation. As the duration is 150 (it is supposed to be subtle), it takes forever to show up the animation. Seems like position is offscreen by more than what I have given. Image I am using for the layer is 728 by 368.
From the documentation:
The position property is located in the middle of the layer.
The code you're using assumes that position is located at the top left of the layer. You can easily fix this by changing your to and from points:
CGPoint fromPoint = CGPointMake(-layerImg.size.width*0.5, layerImg.size.height*0.5);
CGPoint toPoint = CGPointMake(layerImg.size.width*1.5, layerImg.size.height*0.5);
Now your layer will animate from off-screen left to off-screen right.

CALayer - remove from view

I'm adding CAShapeLayer with some CABasicAnimation. I want to be able to remove the layer and draw it again but I can't succeed with this.
- (void)drawRect:(CGRect)rect {
[self drawLayer];
}
- (void)drawLayer {
if (_alayer && _layer.superlayer) {
[_alayer removeFromSuperlayer];
_alayer = nil;
}
_alayer = [[CAShapeLayer alloc] init];
_alayer.path = [self myPath].CGPath;
_alayer.strokeColor = [UIColor redColor].CGColor;
_alayer.fillColor = [UIColor clearColor].CGColor;
_alayer.lineWidth = 2.f;
_alayer.strokeStart = 0.f;
_alayer.strokeEnd = 1.f;
[self.layer addSublayer:_alayer];
// animate
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
animation.duration = 2.f;
animation.fromValue = #0.f;
animation.toValue = #1.f;
[_alayer addAnimation:animateStrokeEnd forKey:#"strokeEndAnimation"];
}
}
However a moment after calling [self setNeedsDisplay]; even though it stops at the breakpoint in drawLayer method, the drawing doesn't disappear and animate in again. alayer is declared as nonatomic, strong property. What am I doing wrong?
You should not call [self drawLayer]; fromm drawRect: because it is called periodically.
Use other viewDidLoad or call it from other method instead
Edited:
drawRect: should only be used for drawing, I don't know if it will even work if you add animation from there.
If you want it to disappear and appear, you should try to add delay using [self performSelector:withObject:afterDelay:].
I think changing hidden or opacity should suffice, you only need to removeAllAnimations to make sure no more animation attached to that layer.
However I think you should try other way than calling drawLayer from drawRect: because I don't it its good practice anyway.
The UIView has its own property layer by default. Please try to change a variable name to shapeLayer or another one.

Circle masked view animating too fast, and not tappable

I'm trying to make a circle-masked image view with animated mask, and played with different solutions. The example below does the job but I've got two problems with it:
1) Why is it that I cannot make the image tappable? Adding eg. a UITapGestureRecognizer does not work. My guess is that the mask prevents the touch actions being propagated to the lower level in the view hierarchy.
2) Animating the mask is running very fast and I cannot adjust the duration using UIView block animation
How can I solve these?
- (void) addCircle {
// this is the encapsulating view
//
base = [[UIView alloc] init];
//
// this is the button background
//
base_bgr = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"c1_bgr.png"]];
base_bgr.center = CGPointMake(60, 140);
[base addSubview:base_bgr];
//
// icon image
//
base_icon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"c1_ico.png"]];
base_icon.center = CGPointMake(186*0.3/2, 182*0.3/2);
base_icon.transform = CGAffineTransformMakeScale(0.3, 0.3);
[base addSubview:base_icon];
//
// the drawn circle mask layer
//
circleLayer = [CAShapeLayer layer];
// Give the layer the same bounds as your image view
[circleLayer setBounds:CGRectMake(0.0f, 0.0f, [base_icon frame].size.width,
[base_icon frame].size.height)];
// Position the circle
[circleLayer setPosition:CGPointMake(186*0.3/2-7, 182*0.3/2-10)];
// Create a circle path.
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:
CGRectMake(0.0f, 0.0f, 70.0f, 70.0f)];
// Set the path on the layer
[circleLayer setPath:[path CGPath]];
[[base layer] setMask:circleLayer];
[self.view addSubview:base];
base.center = CGPointMake(100, 100);
base.userInteractionEnabled = YES;
base_bgr.userInteractionEnabled = YES;
base_icon.userInteractionEnabled = YES;
//
// NOT working: UITapGestureRecognizer
//
UITapGestureRecognizer *tapgesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapit:)];
[base_icon addGestureRecognizer:tapgesture];
//
// BAD but WORKS :) properly positioned UIButton over the masked image
//
base_btn = [UIButton buttonWithType:UIButtonTypeCustom];
base_btn.frame = CGRectMake(base.frame.origin.x, base.frame.origin.y, base_icon.frame.size.width, base_icon.frame.size.height);
[base_btn addTarget:self action:#selector(tapit:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:base_btn];
}
This is the tap handler, and here's the mask animation. Whatever number I tried in duration, it is animating fast - approximately 0.25 second, and I cannot adjust it.
- (void) tapit:(id) sender {
//...
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^ {
[circleLayer setTransform:CATransform3DMakeScale(10.0, 10.0, 1.0)];
}
completion:^(BOOL finished) {
// it is not necessary if I manage to make the icon image tappable
base_btn.frame = [base convertRect:base_icon.frame toView:self.view];
}];
}
}
1) touches are not propagated down from base because it's initiated without a frame, so its frame will be CGRectZero. Views don't get touch events that start outside of their bounds. Simply set a valid frame on base that includes entire tap target.
2) setTransform: on a layer invokes an implicit animation which uses Core Animation's default duration of 0.25 (you guessed it right :)). The best solution would be to use CABasicAnimation instead of UIView-based animation. Something like this:
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.toValue = #(10.0f);
scaleAnimation.duration = 2;
[circleLayer addAnimation:scaleAnimation forKey:nil];
Note: by default, CABasicAnimation will remove itself from a layer when complete and the layer will snap back to old values. You can prevent it by for example setting that animation's removedOnCompletion property to NO and removing it yourself later using CALayer's removeAnimationForKey: method (just set a key instead of passing nil wheen adding the animation), but that depends on what exactly you want to accomplish with this.

iOS CAKeyFrameAnimation Scaling Flickers at animation end

In another test of Key Frame animation I am combining moving a UIImageView (called theImage) along a bezier path and scaling larger it as it moves, resulting in a 2x larger image at the end of the path. My initial code to do this has these elements in it to kick off the animation:
UIImageView* theImage = ....
float scaleFactor = 2.0;
....
theImage.center = destination;
theImage.transform = CGAffineTransformMakeScale(1.0,1.0);
CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:#"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(theImage.image.size.height*scaleFactor, theImage.image.size.width*scaleFactor)]];
resizeAnimation.fillMode = kCAFillModeBackwards;
resizeAnimation.removedOnCompletion = NO;
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.path = [jdPath path].CGPath;
pathAnimation.fillMode = kCAFillModeBackwards;
pathAnimation.removedOnCompletion = NO;
CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:pathAnimation, resizeAnimation, nil];
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
group.removedOnCompletion = NO;
group.duration = duration;
group.delegate = self;
[theImage.layer addAnimation:group forKey:#"animateImage"];
Then, when the animation completes I want to retain the image at the larger size, so I implement:
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
theImage.transform = CGAffineTransformMakeScale(scaleFactor,scaleFactor);
}
This all works .. sort of. The problem is that at the end of the animation theImage flickers for a brief moment - just enough to make it look bad. I am guessing that this is the transition at the end of the animation where I set the transform to the new size.
In experimenting with this I tried a slightly different form of the above, but still got the same flicker:
CAKeyframeAnimation *resizeAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform"];
NSValue* startSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, 1.0, 1.0, 1.0)];
NSValue* endSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, scaleFactor, scaleFactor, 1.0)];
NSArray* sizeKeys = [NSArray arrayWithObjects:startSizeKey, endSizeKey, nil];
[resizeAnimation setValues:sizeKeys];
....
theImage.transform = CGAffineTransformMakeScale(scaleFactor,scaleFactor);
But when I ended the animation at the same size as the original, there was NO flicker:
CAKeyframeAnimation *resizeAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform"];
NSValue* startSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, 1.0, 1.0, 1.0)];
NSValue* middleSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, scaleFactor, scaleFactor, 1.0)];
NSValue* endSizeKey = [NSValue valueWithCATransform3D:CATransform3DScale (theImage.layer.transform, 1.0, 1.0, 1.0)];
NSArray* sizeKeys = [NSArray arrayWithObjects:startSizeKey, middleSizeKey, endSizeKey, nil];
[resizeAnimation setValues:sizeKeys];
....
theImage.transform = CGAffineTransformMakeScale(1.0,1.0);
So my big question is how can I animate this image without the flicker, and end up with a different size at the end of the animation?
Edit March 2nd
My initial tests were with scaling the image up. I just tried scaling it down (IE scaleFactor = 0.4) and the flickering was a lot more visible, and a lot more obvious as to what I am seeing. This was the sequence of events:
Original sized image is painted on the screen at the starting location.
As the image moves along the path it shrinks smoothly.
The fully shrunk image arrives at the end of the path.
The image is then painted at its original size.
The image is finally painted at its shrunken size.
So it seems to be step 4 that is the flickering that I am seeing.
Edit March 22
I have just uploaded to GitHub a demo project that shows off the moving of an object along a bezier path. The code can be found at PathMove
I also wrote about it in my blog at Moving objects along a bezier path in iOS
It can be tricky to animate a view's layer using Core Animation. There are several things that make it confusing:
Setting an animation on a layer doesn't change the layer's properties. Instead, it changes the properties of a “presentation layer” that replaces the original “model layer” on the screen as long as the animation is applied.
Changing a layer's property normally adds an implicit animation to the layer, with the property name as the animation's key. So if you want to explicitly animate a property, you usually want to set the property to its final value, then add an animation whose key is the property name, to override the implicit animation.
A view normally disables implicit animations on its layer. It also mucks around with its layer's properties in other somewhat mysterious ways.
Also, it's confusing that you animate the view's bounds to scale it up, but then switch to a scale transformation at the end.
I think the easiest way to do what you want is to use the UIView animation methods as much as possible, and only bring in Core Animation for the keyframe animation. You can add the keyframe animation to the view's layer after you've let UIView add its own animation, and your keyframe animation will override the animation added by UIView.
This worked for me:
- (IBAction)animate:(id)sender {
UIImageView* theImage = self.imageView;
CGFloat scaleFactor = 2;
NSTimeInterval duration = 1;
UIBezierPath *path = [self animationPathFromStartingPoint:theImage.center];
CGPoint destination = [path currentPoint];
[UIView animateWithDuration:duration animations:^{
// UIView will add animations for both of these changes.
theImage.transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor);
theImage.center = destination;
// Prepare my own keypath animation for the layer position.
// The layer position is the same as the view center.
CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
positionAnimation.path = path.CGPath;
// Copy properties from UIView's animation.
CAAnimation *autoAnimation = [theImage.layer animationForKey:#"position"];
positionAnimation.duration = autoAnimation.duration;
positionAnimation.fillMode = autoAnimation.fillMode;
// Replace UIView's animation with my animation.
[theImage.layer addAnimation:positionAnimation forKey:positionAnimation.keyPath];
}];
}
CAAnimations will flicker at the end if the terminal state was assigned in such a way that it itself created an implicit animation. Keep in mind CAAnimations are temporary adjustments of an object properties for the purposes of visualizing transition. When the animation done, if the layer's state is still the original starting state, that is what is going to be displayed ever so temporarily until you set the final layer state, which you do in your animationDidStop: method.
Furthermore, your animation is adjusting the bounds.size property of your layer, so you should similarly set your final state rather than using the transform adjustment as your final state. You could also use the transform property as the animating property in the animation instead of bounds.size.
To remedy this, immediately after assigning the animation, change the layer's permeant state to your desired terminal state so that when the animation completes there will be no flicker, but do so in such a manner to no trigger an implicit animation before the animation begins. Specifically, in your case you should do this at the end of your animation set up:
UIImageView* theImage = ....
float scaleFactor = 2.0;
....
theImage.center = destination;
theImage.transform = CGAffineTransformMakeScale(1.0,1.0);
CGSize finalSize = CGSizeMake(theImage.image.size.height*scaleFactor, theImage.image.size.width*scaleFactor);
CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:#"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:finalSize]];
resizeAnimation.fillMode = kCAFillModeBackwards;
resizeAnimation.removedOnCompletion = NO;
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.path = [jdPath path].CGPath;
pathAnimation.fillMode = kCAFillModeBackwards;
pathAnimation.removedOnCompletion = NO;
CAAnimationGroup* group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObjects:pathAnimation, resizeAnimation, nil];
group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
group.removedOnCompletion = NO;
group.duration = duration;
group.delegate = self;
[theImage.layer addAnimation:group forKey:#"animateImage"];
[CATransaction begin];
[CATransaction setDisableActions:YES];
theImage.bounds = CGRectMake( theImage.bounds.origin.x, theImage.bounds.origin.y, finalSize.width, finalSize.height );
[CATransaction commit];
and then remove the transform adjustment in your animationDidStop: method.
I was experimenting with some CAAnimations this week and was noticing that there was a flickering at the end of my animations. In particular, I would animation from a circle to a square, while changing the fillColor as well.
Each CAAnimation has a property called removedOnCompletion which defaults to YES. This means that the animation will disappear (i.e. transitions, scales, rotations, etc.) when the animation completes and you'll be left with the original layer.
Since you already have set your removedOnCompletion properties to NO, I would suggest trying to shift your execution of your animations to use CATransactions, instead of delegates and animationDidStop...
[CATransaction begin];
[CATransaction setDisableActions:YES];
[CATransaction setCompletionBlock: ^{ theImage.transform = ...}];
// ... CAAnimation Stuff ... //
[CATransaction commit];
You put the transaction's completion block call before you create your animations, as per:
http://zearfoss.wordpress.com/2011/02/24/core-animation-catransaction-protip/
The following is from one of my methods:
[CATransaction begin];
CABasicAnimation *animation = ...;
animation.fromValue = ...;
animation.toValue = ...;
[CATransaction setCompletionBlock:^ { self.shadowRadius = _shadowRadius; }];
[self addAnimation:animation forKey:#"animateShadowOpacity"];
[CATransaction commit];
And, I constructed this animation and it works fine for me with no glitches at the end:
The setup and trigger are custom methods I have in a window, and i trigger the animation on mousedown.
UIImageView *imgView;
UIBezierPath *animationPath;
-(void)setup {
canvas = (C4View *)self.view;
imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"img256.png"]];
imgView.frame = CGRectMake(0, 0, 128, 128);
imgView.center = CGPointMake(384, 128);
[canvas addSubview:imgView];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[UIImageView animateWithDuration:2.0f animations:^{
[CATransaction begin];
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.duration = 2.0f;
pathAnimation.calculationMode = kCAAnimationPaced;
animationPath = [UIBezierPath bezierPath];
[animationPath moveToPoint:imgView.center];
[animationPath addLineToPoint:CGPointMake(128, 512)];
[animationPath addLineToPoint:CGPointMake(384, 896)];
pathAnimation.path = animationPath.CGPath;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
[imgView.layer addAnimation:pathAnimation forKey:#"animatePosition"];
[CATransaction commit];
CGFloat scaleFactor = 2.0f;
CGRect newFrame = imgView.frame;
newFrame.size.width *= scaleFactor;
newFrame.size.height *= scaleFactor;
newFrame.origin = CGPointMake(256, 0);
imgView.frame = newFrame;
imgView.transform = CGAffineTransformRotate(imgView.transform,90.0*M_PI/180);
}];
}

Problem during page flip

I am using this code to flip my view. but the problem is when the flip is complete the view does not come back to its original position. I have tried to set the frame to change its position but its not working as expected.
- (void) pageOpenView:(UIView *)viewToOpen duration:(NSTimeInterval)duration withFlipDirection:(NSString*)direction {
// Remove existing animations before stating new animation
[viewToOpen.layer removeAllAnimations];
// Make sure view is visible
viewToOpen.hidden = NO;
// disable the view so it’s not doing anythign while animating
viewToOpen.userInteractionEnabled = NO;
// Set the CALayer anchorPoint to the left edge and
// translate the button to account for the new
// anchorPoint. In case you want to reuse the animation
// for this button, we only do the translation and
// anchor point setting once.
if (viewToOpen.layer.anchorPoint.x != 0.0f) {
viewToOpen.layer.anchorPoint = CGPointMake(0.0f, 0.5f);
viewToOpen.center = CGPointMake(viewToOpen.center.x - viewToOpen.bounds.size.width/2.0f, viewToOpen.center.y);
}
// create an animation to hold the page turning
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
transformAnimation.removedOnCompletion = NO;
transformAnimation.duration = duration;
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
// start the animation from the current state
transformAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
// this is the basic rotation by 90 degree along the y-axis
CATransform3D endTransform = CATransform3DMakeRotation(3.141f,
0.0f,
-1.0f,
0.0f);
// these values control the 3D projection outlook
// endTransform.m34 = 0.001f;
// endTransform.m14 = -0.0015f;
transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];
// Create an animation group to hold the rotation
CAAnimationGroup *theGroup = [CAAnimationGroup animation];
// Set self as the delegate to receive notification when the animation finishes
theGroup.delegate = self;
theGroup.duration = duration;
theGroup.fillMode = kCAFillModeBoth;
// CAAnimation-objects support arbitrary Key-Value pairs, we add the UIView tag
// to identify the animation later when it finishes
[theGroup setValue:[NSNumber numberWithInt:viewToOpen.tag] forKey:#"viewToOpenTag"];
// Here you could add other animations to the array
theGroup.animations = [NSArray arrayWithObjects:transformAnimation, nil];
theGroup.removedOnCompletion = NO;
// Add the animation group to the layer
[viewToOpen.layer addAnimation:theGroup forKey:#"flipViewOpen"];
}
Any help would be appreciated.
Thanks in advance.
Arvind
Well solved it by myself.
Just removed any animation before changing its frame by using this method:
[myView.layer removeAllAnimations];
and now its working fine.
Thanks everyone for time.

Resources