最近根据产品需求, 更改翻转动画, 很多时候我们只是改一下 to view 的 frame 来满足需求, 但当要 from view 动起来就出现很多坑了.
首先说一下通过 viewControllerForKey
然后.view
来获取 to view 和 from view 与使用viewForKey
来获取的区别, 如果 to 和 from view 都与 animator 关联, 那么就没有区别了, 但苹果在这里设置了一个坑, 解释如下:
(本文说的 from view 是 present 时候的 from view, dismiss 时候的 to view)
1 2 3 4 5
| // Currently only two keys are defined by the system - // UITransitionContextFromViewKey, and UITransitionContextToViewKey // viewForKey: may return nil which would indicate that the animator should not // manipulate the associated view controller's view. - (nullable __kindof UIView *)viewForKey:(UITransitionContextViewKey)key NS_AVAILABLE_IOS(8_0);
|
ok, 如果使用 viewForKey
获取不到 view, 那么我们使用 viewControllerForKey
获取 view 不就肯定没问题了吗?
答案是错误的, 因为 如果 to 和 from view 没和 animator 关联, 那么这个 view 就不可以加交互动画, 当你 dismiss 的时候动画立刻执行完成, 根本不受 updateInteractiveTransition
的控制, 说到这里我们必须说一下什么情况会发生未关联这种情况, 看苹果解释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // If NO is returned from -shouldRemovePresentersView, the view associated // with UITransitionContextFromViewKey is nil during presentation. This // intended to be a hint that your animator should NOT be manipulating the // presenting view controller's view. For a dismissal, the -presentedView // is returned. // // Why not allow the animator manipulate the presenting view controller's // view at all times? First of all, if the presenting view controller's // view is going to stay visible after the animation finishes during the // whole presentation life cycle there is no need to animate it at all — it // just stays where it is. Second, if the ownership for that view // controller is transferred to the presentation controller, the // presentation controller will most likely not know how to layout that // view controller's view when needed, for example when the orientation // changes, but the original owner of the presenting view controller does. UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey]; // Indicate whether the view controller's view we are transitioning from will be removed from the window in the end of the // presentation transition // (Default: NO) @property(nonatomic, readonly) BOOL shouldRemovePresentersView;
|
解释具体位置
shouldRemovePresentersView
这个属性在哪里那?
苹果提供 管理 交互动画的 控制器 UIPresentationController
,
只要继承这个类, 并重写你需要的方法, 就可以在交互过程中, 完成你想要的效果, 重写下面方法:
1 2 3 4
| - (void)presentationTransitionWillBegin; - (void)presentationTransitionDidEnd:(BOOL)completed; - (void)dismissalTransitionWillBegin; - (void)dismissalTransitionDidEnd:(BOOL)completed;
|
说了这么多, 回到主题, 如何让 from view 和 animator 关联,
只要继承 UIPresentationController
类, 自定义一个SomePresentationController
重写 shouldRemovePresentersView
get方法, 返回 YES, 就关联了, default 是 NO, 如果不重写, 你永远获取不到 from view.
同时, 需要实现 UIViewControllerTransitioningDelegate
的相应代理方法, 如下:
1 2 3 4
| - (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source { SomePresentationController *presentation = [[SomePresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting]; return presentation; }
|
1 2 3
| - (BOOL)shouldRemovePresentersView { return YES; }
|
最后说几句, 如果不看苹果的那个 demo , 你可能永远不知道自己错哪了, 当我看到下面的那几句解释, 整个人都释然了.
1 2 3 4 5
| // If NO is returned from -shouldRemovePresentersView, the view associated // with UITransitionContextFromViewKey is nil during presentation. This // intended to be a hint that your animator should NOT be manipulating the // presenting view controller's view. For a dismissal, the -presentedView // is returned.
|
苹果事例链接
苹果的 demo