现在,这个问题被部分地问了很多,但没有人真正考虑如何(或何时)消息 -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 内):
- 添加childView(会自动调用
-willMoveToParentViewController
) -addSubview
将调用-viewWillAppear
- 当动画结束时,
-addSubview
将调用-viewDidAppear
- 在完成 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];
}];
}
流程是这样的:
- 手动调用
-willMoveToParentView:nil
通知它将被移除 - 当动画结束时,
-viewWillDisappear
和-viewDidDisappear
将同时调用(错误!)并且-removeFromParentViewController
将自动调用-didMoveToParentViewController:nil
.
如果我现在将 -removeFromSuperview
移动到动画 block 中,事件将被正确发送,但 View 会在动画开始时而不是在动画结束时被移除(这是部分这是没有意义的,遵循 -addSubview
的行为)。
最佳答案
您的问题是关于删除 View Controller ,因为 viewWillDisappear
和 viewDidDisappear
是 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];
}];
因此,流程将是:
- 第一个
willMoveToParentViewController:
将调用带有 nil 参数的 - 动画 block 将启动, View 会将其 alpha 属性设置为 0
- 当动画完成时,完成 block 将开始执行...
[self.childViewController.view removeFromSuperview];
会先被调用- 然后调用childViewController中的
viewWillDissapear:
- 然后
[self.childViewController didMoveToParentViewController:self];
- 最后
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/