Completion block for popViewController

后端 未结 18 1593
离开以前
离开以前 2020-12-04 06:43

When dismissing a modal view controller using dismissViewController, there is the option to provide a completion block. Is there a similar equivalent for

相关标签:
18条回答
  • 2020-12-04 07:24

    I had the same issue. And because I had to use it in multiple occasions, and within chains of completion blocks, I created this generic solution in an UINavigationController subclass:

    - (void) navigationController:(UINavigationController *) navigationController didShowViewController:(UIViewController *) viewController animated:(BOOL) animated {
        if (_completion) {
            dispatch_async(dispatch_get_main_queue(),
            ^{
                _completion();
                _completion = nil;
             });
        }
    }
    
    - (UIViewController *) popViewControllerAnimated:(BOOL) animated completion:(void (^)()) completion {
        _completion = completion;
        return [super popViewControllerAnimated:animated];
    }
    

    Assuming

    @interface NavigationController : UINavigationController <UINavigationControllerDelegate>
    

    and

    @implementation NavigationController {
        void (^_completion)();
    }
    

    and

    - (id) initWithRootViewController:(UIViewController *) rootViewController {
        self = [super initWithRootViewController:rootViewController];
        if (self) {
            self.delegate = self;
        }
        return self;
    }
    
    0 讨论(0)
  • 2020-12-04 07:24

    Working with or without animation properly, and also includes popToRootViewController:

     // updated for Swift 3.0
    extension UINavigationController {
    
      private func doAfterAnimatingTransition(animated: Bool, completion: @escaping (() -> Void)) {
        if let coordinator = transitionCoordinator, animated {
          coordinator.animate(alongsideTransition: nil, completion: { _ in
            completion()
          })
        } else {
          DispatchQueue.main.async {
            completion()
          }
        }
      }
    
      func pushViewController(viewController: UIViewController, animated: Bool, completion: @escaping (() ->     Void)) {
        pushViewController(viewController, animated: animated)
        doAfterAnimatingTransition(animated: animated, completion: completion)
      }
    
      func popViewController(animated: Bool, completion: @escaping (() -> Void)) {
        popViewController(animated: animated)
        doAfterAnimatingTransition(animated: animated, completion: completion)
      }
    
      func popToRootViewController(animated: Bool, completion: @escaping (() -> Void)) {
        popToRootViewController(animated: animated)
        doAfterAnimatingTransition(animated: animated, completion: completion)
      }
    }
    
    0 讨论(0)
  • 2020-12-04 07:25

    I know an answer has been accepted over two years ago, however this answer is incomplete.

    There is no way to do what you're wanting out-of-the-box

    This is technically correct because the UINavigationController API doesn't offer any options for this. However by using the CoreAnimation framework it's possible to add a completion block to the underlying animation:

    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        // handle completion here
    }];
    
    [self.navigationController popViewControllerAnimated:YES];
    
    [CATransaction commit];
    

    The completion block will be called as soon as the animation used by popViewControllerAnimated: ends. This functionality has been available since iOS 4.

    0 讨论(0)
  • 2020-12-04 07:25

    Use the next extension on your code: (Swift 4)

    import UIKit
    
    extension UINavigationController {
    
        func popViewController(animated: Bool = true, completion: @escaping () -> Void) {
            CATransaction.begin()
            CATransaction.setCompletionBlock(completion)
            popViewController(animated: animated)
            CATransaction.commit()
        }
    
        func pushViewController(_ viewController: UIViewController, animated: Bool = true, completion: @escaping () -> Void) {
            CATransaction.begin()
            CATransaction.setCompletionBlock(completion)
            pushViewController(viewController, animated: animated)
            CATransaction.commit()
        }
    }
    
    0 讨论(0)
  • 2020-12-04 07:28

    I made a Swift version with extensions with @JorisKluivers answer.

    This will call a completion closure after the animation is done for both push and pop.

    extension UINavigationController {
        func popViewControllerWithHandler(completion: ()->()) {
            CATransaction.begin()
            CATransaction.setCompletionBlock(completion)
            self.popViewControllerAnimated(true)
            CATransaction.commit()
        }
        func pushViewController(viewController: UIViewController, completion: ()->()) {
            CATransaction.begin()
            CATransaction.setCompletionBlock(completion)
            self.pushViewController(viewController, animated: true)
            CATransaction.commit()
        }
    }
    
    0 讨论(0)
  • 2020-12-04 07:30

    Cleaned up Swift 4 version based on this answer.

    extension UINavigationController {
        func pushViewController(_ viewController: UIViewController, animated: Bool, completion: @escaping () -> Void) {
            self.pushViewController(viewController, animated: animated)
            self.callCompletion(animated: animated, completion: completion)
        }
    
        func popViewController(animated: Bool, completion: @escaping () -> Void) -> UIViewController? {
            let viewController = self.popViewController(animated: animated)
            self.callCompletion(animated: animated, completion: completion)
            return viewController
        }
    
        private func callCompletion(animated: Bool, completion: @escaping () -> Void) {
            if animated, let coordinator = self.transitionCoordinator {
                coordinator.animate(alongsideTransition: nil) { _ in
                    completion()
                }
            } else {
                completion()
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题