2

现在,这个问题部分地被问了很多,但没有人真正考虑如何(或何时)发送消息-viewWillDisappear& -viewDidDisappear。几乎每个示例都使用以下设计:

[UIView animateWithDuration:0.5
    delay:1.0
    options: UIViewAnimationCurveEaseOut
    animations:^{
        yourView.alpha = 0;
    }completion:^(BOOL finished){
        [yourView removeFromSuperview]; // Called on complete
    }];

这样做的问题是这些消息都将在动画结束时发送!现在,-addSubview可以进行动画处理(如果放在动画块内),它将以正确的时间差发送相应的消息( -viewWillAppear& )。-viewDidAppear所以自然会放在-removeFromSuperview动画块内。这将正确发送消息,但实际上视图会立即被删除,从而制作动画......好吧,它不会动画,因为没有任何东西可以动画!

这是苹果故意的吗?如果是这样,为什么?你如何正确地做到这一点?

谢谢!

编辑。

只是为了澄清我在做什么:我有一个自定义的 segue,从顶部垂直动画一个 Child-ViewController ,它可以使用以下代码按预期工作:

    -(void)perform{
        UIViewController *srcVC = (UIViewController *) self.sourceViewController;
        UIViewController *destVC = (UIViewController *) self.destinationViewController;

        destVC.view.transform = CGAffineTransformMakeTranslation(0.0f, -destVC.view.frame.size.height);
        [srcVC addChildViewController:destVC];
        [UIView animateWithDuration:0.5f
                         animations:^{
                             destVC.view.transform = CGAffineTransformMakeTranslation(0.0f, 0.0f);
                             [srcVC.view addSubview:destVC.view];
                         }
                         completion:^(BOOL finished){
                             [destVC didMoveToParentViewController:srcVC];
                         }];
    }

在这里它将按以下顺序发生(感谢-addSubview在动画块内):

  1. 添加 childView(将自动调用-willMoveToParentViewController
  2. -addSubview将调用-viewWillAppear
  3. 当动画结束时,-addSubview将调用-viewDidAppear
  4. -didMoveToParentViewController在完成块内手动调用

上面是确切的预期行为(就像内置的转换行为一样)。

使用以下代码执行上述 segue 但向后(使用 unwindSegue):

-(void)perform{
    UIViewController *srcVC = (UIViewController *) self.sourceViewController;

    srcVC.view.transform = CGAffineTransformMakeTranslation(0.0f, 0.0f);
    [srcVC willMoveToParentViewController:nil];
    [UIView animateWithDuration:5.5f
                     animations:^{
                         srcVC.view.transform = CGAffineTransformMakeTranslation(0.0f, -srcVC.view.frame.size.height);
                     }
                     completion:^(BOOL finished){
                         [srcVC.view removeFromSuperview]; // This can be done inside the animations-block, but will actually remove the view at the same time ´-viewWillDisappear´ is invoked, making no sense!
                         [srcVC removeFromParentViewController];
                     }];
}

流程将是这样的:

  1. 手动调用-willMoveToParentView:nil通知将被移除
  2. 当动画结束时,两个-viewWillDisappear&-viewDidDisappear会同时被调用(错误!)并且-removeFromParentViewController会自动调用-didMoveToParentViewController:nil.

如果我现在进入-removeFromSuperview动画块,事件将被正确发送,但是当动画开始而不是动画结束时视图被删除(这是没有意义的部分,遵循-addSubview行为方式)。

4

1 回答 1

1

您的问题是关于删除视图控制器,因为viewWillDisappearviewDidDisappear是视图控制器的方法。

viewWillDisappear:将从完成块中调用,而不是更早,因为这是您说要从主视图中删除子视图的地方。

如果您想在该点之前删除某些属性,则在子控制器覆盖willMoveToParentViewController:方法中。此方法将在动画块之前调用。这是代码示例:

//Prepare view for removeing.
[self.childViewController willMoveToParentViewController:nil];
[UIView animateWithDuration:0.5
                      delay:1.0
                    options: UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     self.childViewController.view.alpha = 0;
                 }completion:^(BOOL finished){
                     [self.childViewController.view removeFromSuperview];
                     [self.childViewController didMoveToParentViewController:self];
                 }];

因此,流程将是:

  1. 首先willMoveToParentViewController:将调用带有 nil 参数的
  2. 动画块将启动,视图将其 alpha 属性设置为 0
  3. 动画完成后,完成块将开始执行...
  4. [self.childViewController.view removeFromSuperview];将首先被调用
  5. 然后viewWillDissapear:在 childViewController 中会被调用
  6. 然后[self.childViewController didMoveToParentViewController:self];
  7. 最后viewDidDissapear:在 childViewController 中执行。

此流程的预请求是您使用以下代码嵌入 childViewController:

[self addChildViewController:self.childViewController];    
[self.view addSubview:self.childViewController.view];
[self.childViewController didMoveToParentViewController:self];
于 2013-11-10T00:02:26.877 回答