【问题标题】:Is it possible to push a View Controller with a completion block?是否可以使用完成块推送视图控制器?
【发布时间】:2014-03-11 17:08:06
【问题描述】:

UINavigationController 的文档不包含带有 completion: 参数的 pushViewController 方法。

【问题讨论】:

  • 我收到了你的问题,但是在 push 时没有办法,但现在会有一个像你期望的那样,否则你可以做到这一点确实出现了 push viewController

标签: ios uiviewcontroller uinavigationcontroller pushviewcontroller


【解决方案1】:

更好的解决方案是通过 CATransaction 包装推送动画并设置完成块。无需处理时间问题。

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    //whatever you want to do after the push
}];
[[self navigationController] pushViewController:viewController animated:YES];
[CATransaction commit];

【讨论】:

  • 这是最好的答案!!
  • 至少使用“慢动画”表明这不是正确的方法。
  • Swift 4 怎么样?我找不到CATransaction.begin() 方法。
  • 也对我不起作用。在动画结束之前执行完成块。
【解决方案2】:

justMartin 的回答对我很有帮助。对于那些刚开始使用 swift API 的人:

CATransaction.begin()
navigationController?.pushViewController(viewController, animated: true)
CATransaction.setCompletionBlock({ 
    //your post animation logic
})
CATransaction.commit()

【讨论】:

  • 谢谢,很棒的提示
  • 这对我来说似乎失败了,以防有一个动画在新的视图控制器加载后立即启动。例如活动指示器。我最终在新视图控制器中创建属性并在推送之前设置它们,而不是在推送后尝试从旧视图控制器调用新视图控制器中的方法。
【解决方案3】:

CATransaction 的解决方案很棒,但还有另一种方法可以做到这一点。您可以让您的控制器成为UINavigationController 的代表并实现didShowViewController 方法:

class FooBarController: UIViewController, UINavigationControllerDelegate {
  func viewDidLoad() {
    self.navigationController?.delegate = self
  }

  func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
    // your awesome completion code here 
  }
}

这种方法可以更方便您的任务

【讨论】:

  • 啊啊啊啊!太棒了!
【解决方案4】:

不确定我是否理解正确,但我在完成块中推送了一个视图控制器,如下所示。在表格视图控制器中,将以下行添加到头文件中:

typedef void(^myCompletion)(BOOL);

然后在类本身中,添加如下方法:

-(void) myMethod:(myCompletion) compblock
{
    compblock(YES);
}

现在在didSelectRowAtIndexPath 中,我调用了myMethod 并在完成块中推送了一个视图控制器。

[self myMethod:^(BOOL finished) {
    if(finished){
        dispatch_async(dispatch_get_main_queue(), ^{
            DVSecondTableViewController *vc = [[DVSecondTableViewController alloc] init];
            [self.navigationController pushViewController:vc animated:YES];
        });
    }
}];

我不确定是否可以将视图控制器推送到主线程之外,所以我将该调用嵌入到 dispatch_async()

【讨论】:

  • OP 询问如何将完成块发送到推送,而不是从完成块推送视图控制器。就像 presentViewController 有完成块一样。
【解决方案5】:

尝试使用-[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;
            }];
        }
    }
}

【讨论】:

    【解决方案6】:

    我会选择@justMartin 的回答。但下面是另一种方法。

    推送动画需要 0.3 秒。因此,如果您想在完成后在此处运行某些功能,请在延迟 0.3 秒后使用 performSelector。

    [self performSelector:@selector(completedPushing:) withObject:nil afterDelay:.3];
    


    new viewController 推送到navigation stack 后,old viewController view 将从视图层次结构中删除。因此这会导致在旧 ViewController 上调用viewDidDisappear。您可以在那里编写completion 代码。不要忘记在 viewDidDisappear 的某个实现点调用 super

    【讨论】:

    • 你不能肯定地说。某人的iDevice可能运行缓慢,因此动画可能需要更长的时间。
    • performSelector:withObject:afterDelay: 的建议不是很好,但 viewDidDisappear 的技巧对我来说非常有用,即使它是一个被解除的模式视图控制器。谢谢你?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-22
    • 2010-12-11
    相关资源
    最近更新 更多