【问题标题】:Is transitionFromViewController just a convenience method in iOS?transitionFromViewController 只是 iOS 中的一种便捷方法吗?
【发布时间】:2012-11-05 17:44:47
【问题描述】:

我不确定我是否完全理解 transitionFromViewController:toViewController:duration:options:animation:completion: 的作用。它只是一种方便的方法吗?

例如,这样做有什么区别......

[self transitionFromViewController:fromViewController
                  toViewController:toViewController
                          duration:0.25
                           options:UIViewAnimationOptionCurveEaseInOut
                        animations:^{
                            fromViewController.view.alpha = 0;
                            toViewController.view.alpha = 1;
                        } completion:^(BOOL finished) {
                            [fromViewController removeFromParentViewController];
                            [toViewController didMoveToParentViewController:self];
                        }];

...还有这个?

[self.view addSubview:toViewController.view];
[UIView animateWithDuration:0.25
                      delay:0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     fromViewController.view.alpha = 0;
                     toViewController.view.alpha = 1;
                 } completion:^(BOOL finished){
                     [fromViewController.view removeFromSuperview];
                     [fromViewController removeFromParentViewController];
                     [toViewController didMoveToParentViewController:self];
                 }];

我问的原因是在某些情况下我需要将子控制器视图添加到容器控制器视图的特定子视图中。使用 transitionFromViewController:toViewController:duration:options:animation:completion: 没有给我这个选项。

【问题讨论】:

  • 当我执行transitionFromViewController 时,我经常在子视图中使用fromViewController.view,它会将toViewController.view 添加到同一个子视图中(这非常重要)。或者你是说你想让toViewController.view进入一个不同的子视图?
  • 不,我想要的和你一样。我试过了,它有效!谢谢!在文档中包含这种漂亮的行为不会有什么坏处。
  • @Rob 感谢您分享这条信息。您应该将其包含在您的答案中。我有完全相同的用例,但不知道该方法会自动将子视图置于正确的位置。节省时间,谢谢!

标签: iphone ios ios5 uiviewcontroller


【解决方案1】:

是的,我认为您是对的:它们在功能上似乎相同(不确定我们是否可以在不了解实现细节的情况下将其称为便捷方法,但很可能)。显然,transitionFromViewController 是为视图控制器的包含而设计的,animateWithDuration 是为视图的通用动画而设计的。

鉴于您显然在进行收容,可能应该使用transitionFromViewController 而不是animateWithDuration。这是明确的技术recommended by Apple。如果您在子视图中有fromViewController.view,则新的toViewController.view 将添加到同一子视图中。

我还建议包括缺少的 willMoveToParentViewControlleraddChildViewController(为了简洁起见,我假设您省略了,但为了完整起见,我包括在内):

[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];

[self transitionFromViewController:fromViewController
                  toViewController:toViewController
                          duration:0.25
                           options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve
                        animations:^{}
                        completion:^(BOOL finished){
                            [fromViewController removeFromParentViewController];
                            [toViewController didMoveToParentViewController:self];
                        }];

另请注意,我使用的是UIViewAnimationOptionTransitionCrossDissolve。如果您要手动设置 alpha,请不要忘记初始化 toViewController.view.alpha,例如:

[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
toViewController.view.alpha = 0.0;

[self transitionFromViewController:fromViewController
                  toViewController:toViewController
                          duration:0.25
                           options:UIViewAnimationOptionCurveEaseInOut
                        animations:{
                            fromViewController.view.alpha = 0.0;
                            toViewController.view.alpha = 1.0;
                        }
                        completion:^(BOOL finished){
                            [fromViewController removeFromParentViewController];
                            [toViewController didMoveToParentViewController:self];
                        }];

【讨论】:

  • +1 请记住,animations 不能为空,如文档中所述。
  • 编辑问题以澄清为什么直接使用animateWithDuration 版本可能有用。
  • 不知道非空动画块。替换为空动画块。我觉得这是一个荒谬的要求,因为以UIViewAnimationOptionTransition 开头的options 通常不需要任何动画块。但事实就是如此。
  • 在 WWDC2011 视频中,Apple 开发人员为动画块传递了 nil 的视图容器遏制
  • 我认为需要注意的是,transitionFromViewController:toViewController: 将确保在正确的时间调用 viewWill/DidAppear 和 viewWill/DidDisappear 方法。提问者的 UIView 动画代码没有这样做。
【解决方案2】:

简答
不,这不仅仅是一种方便的方法,因为在两个子控制器上调用外观方法的时间不同。

长答案
关于 -->

[self.view addSubview:toViewController.view];
[UIView animateWithDuration:0.25
                      delay:0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     fromViewController.view.alpha = 0;
                     toViewController.view.alpha = 1;
                 } completion:^(BOOL finished){
                     [fromViewController.view removeFromSuperview];
                     [fromViewController removeFromParentViewController];
                     [toViewController didMoveToParentViewController:self];
                 }];

当你打电话时,幕后会发生什么

[self.view addSubview:toViewController.view];

是这样的(当然这不完整)

[toViewController.view viewWillAppear:false]; <-- meaning not animated
//Add the view to the view hierarchy
//Layout the view
[toViewController.view viewDidAppear:false]; <-- meaning not animated

之后,当您执行动画时 toViewController “认为”它的视图已经可见并且没有动画呈现。 fromViewController 也是如此。在您的动画期间,fromViewController 不知道它的视图被解除,因为 viewWill/DidDisappear 将在您调用动画之后调用

[fromViewController.view removeFromSuperview];


另一方面——>

[self transitionFromViewController:fromViewController
              toViewController:toViewController
                      duration:0.25
                       options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{}
                    completion:^(BOOL finished){
                        [fromViewController removeFromParentViewController];
                        [toViewController didMoveToParentViewController:self];
                    }];

做这样的事情

[UIView animateWithDuration:yourDuration
                      delay:yourDelay
                    options:yourOptions
                 animations:^{
                     [toViewController viewWillAppear:true];
                     [fromViewController viewWillDisappear:true];
                     //Add toViewcontroller.view to the view hierarchy
                     //Layout the toViewcontroller.view --> changes here are not animated. (There is no "previous state" as the view has just been added to the hierarchy)
                     //Call your animation-block
                 } completion:^(BOOL finished){
                     [toViewController viewDidAppear:true];
                     [fromViewController.view removeFromSuperview];
                     [fromViewController viewDidDisappear:true];
                     //Call your completion-block
                 }];

这么长的回答简短
viewWillAppear 和 viewWillDisappear 在动画块内被调用并被传递为真。这对您的应用程序可能有用也可能没用,因此这两种方法之间可能存在差异,也可能没有差异。

【讨论】:

    【解决方案3】:

    正如文档所说,它旨在用于在两个子视图控制器之间进行转换,而不是同一个子视图控制器的两个视图。

    在您的第一个代码 sn-p 中,您传递的 toViewController 与前两个参数相同。这是两个不同的视图控制器,而不是同一个。

    如果您只是切换同一视图控制器的视图,则您的第二个示例更合适。

    【讨论】:

    • 我的意思是使用两个不同的视图控制器。你回答时我正在编辑代码。道歉。
    猜你喜欢
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 2021-01-06
    相关资源
    最近更新 更多