I have an issue with the following code. When I execute it, There is a undefined delay withing first [CATransaction commit] and CompletionBlock:. No idea what is happening there. This only happen when the app run on the device.
This is the time log,
2013-04-22 15:59:50.893 MyApp[27038:907] ***** A
2013-04-22 **15:59:50.894** MyApp[27038:907] ***** B
2013-04-22 **15:59:53.161** MyApp[27038:907] ***** C
2013-04-22 15:59:53.162 MyApp[27038:907] ***** D
2013-04-22 15:59:53.164 MyApp[27038:907] ***** E
2013-04-22 15:59:53.967 MyApp[27038:907] ***** F
-
NSLog(#"***** A");
[CATransaction begin];
[CATransaction setCompletionBlock:^{
[CATransaction begin];
NSLog(#"***** D");
for (UIView *view in [masterTableView subviews])
{
if (view.tag == 501)
{
[view removeFromSuperview];
break;
}
}
[self.view sendSubviewToBack:masterTableView];
[self.view bringSubviewToFront:detailView];
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setDuration:.8];
[animation setSubtype:transitionFromRight?kCATransitionFromRight:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setCompletionBlock:^{
NSLog(#"***** F");
for (UIView *view in [detailView subviews])
{
if (view.tag == 502)
{
[view removeFromSuperview];
break;
}
}
[self addDetailView];
[self.view sendSubviewToBack:detailView];
[self.view bringSubviewToFront:masterTableView];
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setDuration:.8];
[animation setSubtype:transitionFromRight?kCATransitionFromRight:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[detailView layer] addAnimation:animation forKey:#"transition"];
}];
[[masterTableView layer] addAnimation:animation forKey:#"transition"];
NSLog(#"***** E");
}];
[CATransaction begin];
[CATransaction setCompletionBlock:^{
NSLog(#"***** C");
for (UIView *view in [self.view subviews])
{
if (view.tag == 500)
{
[view removeFromSuperview];
break;
}
}
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setDuration:0];
[animation setSubtype:transitionFromRight?kCATransitionFromRight:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[dummyView layer] addAnimation:animation forKey:#"transition"];
}];
[CATransaction commit];
[CATransaction commit];
NSLog(#"***** B");
Have I mistaken some thing ?? Please help.
As I realized CATransaction creates snap shots of the views which I animate. So it gets some time for that task and some delay occur because of that.
So as a solution now I'm animating a UIImageView with the snap shot image of the view. So now the undefined issue was fixed.
Related
My problem is that I've 2 graphics animation one after the other, but they are done together.
I thought to write a method with completion block, but or I'm doing something wrong, or there is another way to do this.
The animation is a uiview that move out of the screen (closeView) and the default animation of viewcontroller closing.
I want the viewcontroller closes when is over the animation of view.
This is what i've done
- (void)closeViewWithCompletion:(void (^) (BOOL finish))handler {
[self closeView];
handler(YES);
}
-(void) closeView{
[self.myview setFrame:CGRectMake(
-self.myview.frame.size.width
, self.myview.frame.origin.y
, self.myview.frame.size.width
, self.view.frame.size.height
)];
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
[animation setDuration:.50];
[animation setDelegate:self];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
CALayer *layer = [self.myview layer];
[layer addAnimation:animation forKey:nil];
[UIView animateWithDuration:0.5 animations:^{
[greyMask setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0]];
} completion:^(BOOL finished) {
[greyMask removeFromSuperview];
}];
}
use:
[vc closeViewWithCompletion:^(BOOL finish) {
[navController popViewControllerAnimated:true];
}
];
call your handler block in completionBlock after your closeView Animation finishes.
- (void)closeViewWithCompletion:(void(^)(BOOL finish))handler {
//closeView Animation
[UIView animateWithDuration:duration delay:0 options: UIViewAnimationOptionCurveEaseOut animations:^{
//code for close view animation
} completion:^(BOOL finished) {
handler(YES) //call your handler in completion block
}];
}
[vc closeViewWithCompletion:^(BOOL finish) {
[self.navigationController popViewControllerAnimated:true];
}];
I'm trying to set the image back to default when i shake the device. the problem is that, the image is processing to default and only afterwards the rippleEffect happens.
I'm trying to do this during the animation, not before nor after.
any ideas?
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
if(motion == UIEventSubtypeMotionShake){
CATransition *animation=[CATransition animation];
[animation setDelegate:self];
[animation setDuration:1.0];
[animation setTimingFunction:UIViewAnimationCurveEaseInOut];
[animation setType:#"rippleEffect"];
//[animation setFillMode:kCAFillModeRemoved];
animation.endProgress=0.99;
[(GPUImageBulgeDistortionFilter *)sepiaFilter setScale:0.0];
[sourcePicture processImage];
[animation setRemovedOnCompletion:NO];
[self.view.layer addAnimation:animation forKey:nil];
}
}
I have two blocks of code (described also in another topic)
- (void)AnimateImage:(NSString*)direction{
self.CurrentAnimal.image = [images objectAtIndex:image_nr];
CATransition *animation = [CATransition animation];
[animation setDuration:1.0];
[animation setType:kCATransitionPush];
if([direction isEqualToString:#"left"]){
[animation setSubtype:kCATransitionFromLeft];
}
else {
[animation setSubtype:kCATransitionFromRight];
}
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[self.CurrentAnimal layer] addAnimation:animation forKey:nil];
}
And
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
//do what you need to do when animation ends...
}
I know that I need to "set the delegate property and implement the method" to catch animationDidStop event but I'm not able to get it working.
Question - How do I set up my .h and .m files so that I'm able to use this method to execute code when CATransition animation stops?
Set up the delegate:
CATransition *animation = [CATransition animation];
....
[animation setDelegate:self];
[animation setDuration:1.0];
[animation setType:kCATransitionPush];
You first have to add the Delegate to the CATransition object you created like that
CATransition *animation = [CATransition animation];
[animation setDelegate = self];
[animation setValue:animation.values.lastObject forKey:#"myAnimationKey"];
If you set a key for your animation, you can exactly check which animation ended. If you have just one animation, you don't need a specific key. If you set a key you can check which animation ended like that:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if(anim == [animation.layer animationForKey:#"myAnimationKey"]){
}
}
How can I get the following animation to work in blocks?
(I need the keyboard to dissappear in the completion handler of the transition animation)
- (void) showNewViewAnimatedSlideAscending:(BOOL)isAscending {
UIView * oldView = self.myView;
UIView * newView = self.myView;
UIView * superView = self.myView.superview;
[oldView removeFromSuperview];
[superView addSubview:newView];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.3];
[animation setType:kCATransitionPush];
if(isAscending) {
[animation setSubtype:kCATransitionFromRight];
} else {
[animation setSubtype:kCATransitionFromLeft];
}
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[superView layer] addAnimation:animation forKey:#"myTransitionAnimation"];
if(self.keyboardVisible) {
[self.view endEditing:YES];
}
}
p.s; I know, I'm removing and showing the same view. This view has received new data just before calling this method. Somehow the view displays correctly and only shows the new data in the 'new' view.
There are another custom UIViewController transition than the 4 natives iOS:
typedef enum {
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
UIModalTransitionStylePartialCurl,
} UIModalTransitionStyle;
Any tips?
You could also try CATransition, for example, the code below shows a transition where a second view pushes your current view out to the right. (Assuming this code is placed in your main view controller).
UIView *appWindow = [self.view superview];
CATransition *animation = [CATransition animation];
[animation setDuration:0.3];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[appWindow addSubview:yourSecondViewController.view];
[self.view removeFromSuperview];
[[appWindow layer] addAnimation:animation forKey:#"showSecondViewController"];