Is it possible to push a View Controller with a co

2020-02-08 03:58发布

问题:

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;
            }];
        }
    }
}