【问题标题】:Why is viewWillDisappear called at the wrong time when using manual view containment?为什么在使用手动视图包含时会在错误的时间调用 viewWillDisappear?
【发布时间】:2014-09-21 03:57:55
【问题描述】:

这就是我使用容器 API 的方式。根据docs 是正确的。

[self.childViewController willMoveToParentViewController:nil];
[UIView animateWithDuration:0.25 animations:^{
    self.childViewController.view.frame = ... // View Animation
} completion:^(BOOL finished) {
    [self.childViewController.view removeFromSuperview]; // triggers `viewWillDisappear`
    [self.childViewController removeFromParentViewController];
}];

我希望在动画开始之前调用viewWillDisappear,并在动画完成后调用viewDidDisappear。但是,它们都是在动画完成后快速连续调用的。

[self.childViewController.view removeFromSuperview]; 移动到动画块可以解决此问题,但代码看起来错误:

[self.childViewController willMoveToParentViewController:nil];
[UIView animateWithDuration:0.25 animations:^{
    self.childViewController.view.frame = ... // View Animation
    [self.childViewController.view removeFromSuperview]; // triggers `viewWillDisappear`
} completion:^(BOOL finished) {
    [self.childViewController removeFromParentViewController];
}];

有谁知道在正确的时间调用viewWillDisappear 的正确方法是什么?

【问题讨论】:

  • “正确”时间是在视图从视图层次结构中删除之前,也就是它发生的时间。也许您应该解释为什么需要在调用时调用它,以及您要实现的目标。

标签: ios objective-c cocoa-touch uiviewcontroller


【解决方案1】:

您没有通知 childViewController 移动到 parentViewController。

[yourViewController didMoveToParentViewController:self]

[self.childViewController willMoveToParentViewController:nil]; 你没有提到谁将成为parentViewController。指出添加 childViewController 的时间是一个很好的做法。那么iOS应该知道什么时候触发viewWillDisappear

您是在通知 viewController 将移动到 parentViewController,但如果您指出哪个 parentViewController 是您的代码将按预期工作,您并没有指出谁是 parentViewController。

当视图准备好离开父视图时,ViewWillDissappear 将被触发。这将在您的 parentViewController 或 viewController 的下一个 willLayoutSubviews 执行中发生,具体取决于您的 viewControllers 的层次结构

     [UIView animateWithDuration:0.25 animations:^{
    [self.childViewController.view removeFromSuperview];
self.childViewController.view.frame = ... // View Animation
    [self.view addSubView:self.childViewController.view];
        } completion:^(BOOL finished) {
            [self.childViewController didMoveToParentViewController:self];
             // triggers `viewWillDisappear`
            [self.childViewController removeFromParentViewController];
        }];

试试看

【讨论】:

  • 我不认为这是正确的,来自文档.. > 如果你正在实现自己的容器视图控制器,它必须在调用 removeFromParentViewController 方法之前调用子视图控制器的 willMoveToParentViewController: 方法,传递在 nil 的父值中。
  • 检查我编辑的答案,这是应该怎么做的,我忘了提到你正在移动框架,但你没有将 childViewController 视图添加到任何父视图。
【解决方案2】:

答案是使用– beginAppearanceTransition:animated: & endAppearanceTransition

如果您正在实现自定义容器控制器,请使用此方法告诉孩子它的视图即将出现或消失。不要直接调用 viewWillAppear:、viewWillDisappear:、viewDidAppear: 或 viewDidDisappear:。

更正后的代码:

[self.childViewController willMoveToParentViewController:nil];
[self.childViewController beginAppearanceTransition:NO animated:YES];
[UIView animateWithDuration:0.25 animations:^{
    self.childViewController.view.frame = ... 
} completion:^(BOOL finished) {
    [self.childViewController.view removeFromSuperview]; 
    [self.childViewController removeFromParentViewController];
    [self.childViewController endAppearanceTransition];
}];

【讨论】:

  • 错字,我认为:发给self.viewController 的消息应该发送给self.childViewController,因为外观转换消息旨在发送给正在转换的孩子。
【解决方案3】:

这是一个 Swift 版本。 它将beginAppearanceTransition 放置在动画闭包中,因此您可以获得类似UINavigationController 的行为:您可以在子视图控制器的viewWillDisappear 中调整动画视图属性并自动获取动画。

let animator = UIViewPropertyAnimator(duration: 0.5, dampingRatio: 1) {
    childViewController.willMove(toParentViewController: self)
    childViewController.beginAppearanceTransition(false, animated: true)
    childViewController.view.frame = ... // View Animation
}
animator.addCompletion { _ in
    childViewController.view.removeFromSuperview()
    childViewController.endAppearanceTransition()
    childViewController.removeFromParentViewController()
}
animator.startAnimation()

注意endAppearanceTransition 必须在view.removeFromSuperview 之后调用,否则系统会将重复的viewWillDisappear viewDidDisappear 方法发送到您的子视图控制器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 2022-01-26
    相关资源
    最近更新 更多