ios - UIView removeFromSuperview 内部动画正确

标签 ios cocoa-touch

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

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

问题在于这些消息都将在动画结束时发送! 现在,-addSubview 可以设置动画(如果放在动画 block 内),它将发送相应的消息(-viewWillAppear & -viewDidAppear)具有正确的时差。所以很自然地人们会将 -removeFromSuperview 放在动画 block 中。这将正确发送消息,但 View 实际上会立即删除,从而制作动画......好吧,它不会动画,因为没有什么可以动画了!

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

谢谢!

编辑。

只是为了弄清楚我在做什么: 我有一个自定义的 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 位于动画 block 内):

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

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

使用以下代码执行上述转场但向后(使用 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 移动到动画 block 中,事件将被正确发送,但 View 会在动画开始时而不是在动画结束时被移除(这是部分这是没有意义的,遵循 -addSubview 的行为)。

最佳答案

您的问题是关于删除 View Controller ,因为 viewWillDisappearviewDidDisappear 是 View Controller 的方法。

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

如果你想在那之前删除一些属性,那么在子 Controller 中覆盖 willMoveToParentViewController: 方法。此方法将在动画 block 之前调用。 这是代码示例:

//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. 动画 block 将启动, View 会将其 alpha 属性设置为 0
  3. 当动画完成时,完成 block 将开始执行...
  4. [self.childViewController.view removeFromSuperview]; 会先被调用
  5. 然后调用childViewController中的viewWillDissapear:
  6. 然后 [self.childViewController didMoveToParentViewController:self];
  7. 最后 viewDidDissapear: 将在 childViewController 中执行。

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

[self addChildViewController:self.childViewController];    
[self.view addSubview:self.childViewController.view];
[self.childViewController didMoveToParentViewController:self];

关于ios - UIView removeFromSuperview 内部动画正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19883568/

相关文章:

ios - Xcode Storyboard 在 UI 元素周围显示蓝色框架。我该如何关闭它?

ios - 有没有办法以编程方式检测 iOS 9 低功耗模式?

ios - 当用 Swift 编写大型应用程序时,我是否需要使用 "init"方法?

iOS >> 更改方向时获取当前可见 View /窗口大小

ios - 设置 UIView 的框架不起作用

iphone - quartz : can't create a rounded rectangle with gradient fill

ios - Affdex iOS SDK "set the licensePath property with a valid file path"错误

ios - 不能在 NSDateFormatter 中的年份之前加上单引号

iphone - 如何从远程推送通知中获取我的应用程序中的notification.alertBody?

ios - 如何在 iOS 中绘制没有抗锯齿/插值的位图?