最近根据产品需求, 更改翻转动画, 很多时候我们只是改一下 to view 的 frame 来满足需求, 但当要 from view 动起来就出现很多坑了.
首先说一下通过 viewControllerForKey
然后.view
来获取 to view 和 from view 与使用viewForKey
来获取的区别, 如果 to 和 from view 都与 animator 关联, 那么就没有区别了, 但苹果在这里设置了一个坑, 解释如下:
(本文说的 from view 是 present 时候的 from view, dismiss 时候的 to view)
// 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
的控制, 说到这里我们必须说一下什么情况会发生未关联这种情况, 看苹果解释:
// 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
,
只要继承这个类, 并重写你需要的方法, 就可以在交互过程中, 完成你想要的效果, 重写下面方法:
- (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
的相应代理方法, 如下:
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source {
SomePresentationController *presentation = [[SomePresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];
return presentation;
}
- (BOOL)shouldRemovePresentersView {
return YES;
}
最后说几句, 如果不看苹果的那个 demo , 你可能永远不知道自己错哪了, 当我看到下面的那几句解释, 整个人都释然了.
// 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.
网友评论