UIActivityIndicatorView keeps animating preceding CATransition pushViewController - objective-c

I'm trying stop the animation on my UIActivityIndicatorView in the same method that I push a view controller using a CATransition fade.
Instead of stopping the animation, then fading to the next view controller, the UIActivityIndicatorView contiues animating throughout the entire fade, no matter how long I set the duration.
Any ideas how I can get the spinning to stop, then push/fade in the same method?
- (void)pushView:(NSNotification *)notification {
[self.activityIndicator stopAnimating];
NextViewController* nextViewController = [[NextViewController alloc] init];
CATransition *transition = [CATransition animation];
transition.duration = 1.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:nextViewController animated:NO];
}
Edit 1
Along the same lines as David's answer, I was able to successfully stopAnimating if I used dispatch_after and delayed for a fraction of a second. Is there a better way to accomplish this?:
- (void)pushView:(NSNotification *)notification {
[self.activityIndicator stopAnimating];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.0001 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void){
NextViewController* nextViewController = [[NextViewController alloc] init];
CATransition *transition = [CATransition animation];
transition.duration = 1.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:nextViewController animated:NO];
});
}

I've run into something similar to this before. What you are running is called Synchronous Execution. In synchronous execution, the UI is not updated until the compiler terminates the function, a.k.a. the }. How do you get around this? Simple. Just run any methods to update the UI in an Asynchronous dispatch:
- (void)pushView:(NSNotification *)notification {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.activityIndicator stopAnimating];
});
NextViewController* nextViewController = [[NextViewController alloc] init];
CATransition *transition = [CATransition animation];
transition.duration = 1.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:nextViewController animated:NO];
});
}
Whoops! I forgot to put the other code in a plain dispatch! Try the edited code and it should work!
This way the [self.activityIndicator stopAnimating]; is run on a priority thread, while the rest of the code in the function is run in the default priority thread, effectively running the code at the same time, the way you would expect it to.
Cheers!

Related

custom animation in setCollectionViewLayout:animated: to enlarge the selected cell

I'm changing layouts when selecting a cell in a uicollectionview and have added a custom animation to the collectionview layer
currently I'm using this code:
[self.collectionView performBatchUpdates:^{
CATransition *transition = [CATransition animation];
transition.duration = 0.5f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionMoveIn;
[self.collectionView.layer addAnimation:transition forKey:nil];
[self.collectionView setCollectionViewLayout:self.horizontalPagingLayout animated:NO];
self.galleryInHorizontalScrollMode = YES;
[self.collectionView setPagingEnabled:YES];
} completion:^(BOOL finished) {
[self reloadData];
}];
I would like to change the animation style (transition.type) such that the selected cell will "grow" (or shrink) to the size of the final cell size defined in the collectionview layout
How can this be done?
I've tried solutions as suggested here but they looked very poor

transition using CATransition

How can I use CATransition to move from one controller to the next so that the view moves up to show the second window. I want the view from controller 1 to move up and show the view from the second controller. How can I do that?
Here's what I am doing?
CATransition *transition = [CATransition animation];
transition.duration = 0.7f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
transition.type = kCATransitionFromBottom;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:destinationController animated: NO];
try this one
CATransition* transition = [CATransition animation];
transition.duration = 0.7f;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade; //kCATransitionMoveIn,kCATransitionReveal, kCATransitionFade, kCATransitionPush,
//transition.subtype = kCATransitionFromTop; //kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromLeft, kCATransitionFromBottom
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[[self navigationController] popViewControllerAnimated:NO];

screen flash when addsubview by CATransition

Many people use this method to add animation on switching views. When I try to add animation effect on adding a subview, the view always flash once。 The reason is that the view add subview immediately at the beginning, after that, the animation starts.
CATransition *transition = [CATransition animation];
transition.duration = 0.35;
transition.removedOnCompletion = NO;
transition.fillMode = kCAFillModeForwards;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromBottom;
transition.delegate = self;
[[animationView layer] addAnimation:transition forKey:#"switchView"];
OtherViewController *otherController = [[OtherViewController alloc]init:cityID];
self.myOtherViewController = otherController;
[otherController release];
[self.view insertSubview:myOtherViewController.view atIndex:1];
What's the reasons of problem? How to implement the animation of loading new view without flash?
After modified fillMode to kCAFillModeBoth, it works.
transition.fillMode = kCAFillModeForwards;

How to animate removeFromSuperview

I animated the appearance of my subview with:
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionReveal;
[webView.layer addAnimation:transition forKey:nil];
[self.view addSubview:webView];
But now I want to remove my subView. How can I add animation to do this? Like other CATransition? When to add this? Before or after addSubview?
Well you could do the animation first and on the animationEndListener call removeFromSuperView
[UIView animateWithDuration:0.5
delay:1.0
options: UIViewAnimationOptionCurveEaseOut
animations:^{
yourView.alpha = 0;
}completion:^(BOOL finished){
[yourView removeFromSuperview];
}];

How do I associate pressing a button in my interface to transferring to another view?

I am trying to make it so that when a UIButton in my toolbar that I set in my xib file is pressed, a new controller is loaded into view.
How do I implement that? I have tried duplicating the FlipViewController, but I don't think you can have more than one of these.
iPad (don't use UINavigationController for the whole screen).
You can switch with a nice animation like this:
(works only in app-delegate unless you change the line commented with // works only in app delegate.
UIViewController *ctrl = [[UIViewController alloc] initWithNibName:#"someXIBStuff" bundle:nil];
CAKeyframeAnimation *theAnimation = [CAKeyframeAnimation animation];
theAnimation.values = [NSArray arrayWithObjects:
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.12,1.12,1)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1,1,1)],
nil];
theAnimation.cumulative = YES;
theAnimation.duration = 0.3;
theAnimation.repeatCount = 0;
theAnimation.removedOnCompletion = YES;
theAnimation.timingFunctions = [NSArray arrayWithObjects:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
nil
];
[self.window.layer addAnimation:theAnimation forKey:#"transform"];
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
transition.delegate = self;
[self.window.layer addAnimation:transition forKey:nil];
self.window.rootViewController = ctrl; // works only in app delegate
[ctrl release];
iPhone:
Use UINavigationController (if possible). If not, you might use the example above.