• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - UIView removeFromSuperview 内动画正确

[复制链接]
菜鸟教程小白 发表于 2022-12-12 16:16:14 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

现在,这个问题部分地被问了很多,但没有人真正考虑如何(或何时)发送消息 -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

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

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



Best Answer-推荐答案


您的问题是关于删除 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: in 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/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap