问题
UINavigationController's documentation contains no pushViewController
methods with a completion:
parameter.
回答1:
I would go with @justMartin's answer . But below is another approach.
push animation take 0.3 seconds.So, if you want to run some function here after completion use performSelector after 0.3 seconds of delay.
[self performSelector:@selector(completedPushing:) withObject:nil afterDelay:.3];
OR
After pushing the new viewController
onto navigation stack
,the old viewController view
is removed from view hierarchy.so this results in call of viewDidDisappear
on old ViewController.You can write your completion
code there. don't forget to call super
at some point of implementation of viewDidDisappear.
回答2:
The better solution would be wrapping the push animation by an CATransaction and set the completionBlock. There's no need to deal with timings.
[CATransaction begin];
[CATransaction setCompletionBlock:^{
//whatever you want to do after the push
}];
[[self navigationController] pushViewController:viewController animated:YES];
[CATransaction commit];
回答3:
justMartin's answer worked great for me. For those new to using swift API:
CATransaction.begin()
navigationController?.pushViewController(viewController, animated: true)
CATransaction.setCompletionBlock({
//your post animation logic
})
CATransaction.commit()
回答4:
Solution with CATransaction
is great but there is another way to do that. You can make your controller a delegate of UINavigationController
and implement didShowViewController
method:
class FooBarController: UIViewController, UINavigationControllerDelegate {
func viewDidLoad() {
self.navigationController?.delegate = self
}
func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
// your awesome completion code here
}
}
This approach can be more convenient for your task
回答5:
Not sure if I understand correctly, but I pushed a view controller in a completion block as follows. In a table view controller, added the following line to the header file:
typedef void(^myCompletion)(BOOL);
Then in the class itself, added the following method:
-(void) myMethod:(myCompletion) compblock
{
compblock(YES);
}
Now in didSelectRowAtIndexPath
, I called myMethod
and in the completion block, pushed a view controller.
[self myMethod:^(BOOL finished) {
if(finished){
dispatch_async(dispatch_get_main_queue(), ^{
DVSecondTableViewController *vc = [[DVSecondTableViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
});
}
}];
I'm not sure if it's okay to push view controllers outside of the main thread, so I embedded that call in a dispatch_async()
.
回答6:
Try using -[UIViewControllerTransitionCoordinator animateAlongsideTransitionInView:animation:completion:]
:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (!self.isPushing) {
self.pushing = YES;
[super pushViewController:viewController animated:animated];
if (!self.transitionCoordinator) {
self.pushing = NO;
} else {
[self.transitionCoordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
self.pushing = NO;
}];
}
}
}
来源:https://stackoverflow.com/questions/21743780/is-it-possible-to-push-a-view-controller-with-a-completion-block