自定义过渡animation不会调用VC生命周期方法

所以我build立了一个自定义的演示过渡animation,除了视图控制器的生命周期方法没有被解雇之外,一切似乎都很好。

在呈现控制器之前,我使用UIModalPresentationCustom风格来保持VC呈现在视图层次结构中,但是一旦我closures了呈现的VC,viewWillAppear和viewDidAppear就不会在我的呈现控制器上调用。 我是否错过了一个步骤,我需要明确地调用这些方法来触发? 我知道手动调用这些方法不是正确的解决scheme。

这是我的解雇animation代码。 我基本上animation的forms覆盖视图收缩到收集视图单元的大小解雇。

 - (void)_animateDismissingTransitionWithContext:(id<UIViewControllerContextTransitioning>)transitionContext { UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UICollectionView *destinationCollectionView = toCollectionViewController.collectionView; UICollectionViewCell *destinationCollectionViewCell = [self _destinationCellFromContext:transitionContext]; UIView *containerView = transitionContext.containerView; // Calculate frames CGRect startFrame = fromEventDetailViewController.detailContainerView.frame; CGRect endFrame = [destinationCollectionView convertRect:destinationCollectionViewCell.frame toView:containerView]; // Add overlay UIView *overlayView = [UIView new]; overlayView.backgroundColor = [UIColor overlayBackground]; overlayView.frame = containerView.bounds; overlayView.alpha = 1.0f; [containerView addSubview:overlayView]; // Add fake detail container view UIView *fakeContainerView = [UIView new]; fakeContainerView.backgroundColor = fromEventDetailViewController.detailContainerView.backgroundColor; fakeContainerView.frame = startFrame; [containerView addSubview:fakeContainerView]; // Hide from view controller fromEventDetailViewController.view.alpha = 0.0f; [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0f usingSpringWithDamping:0.75f initialSpringVelocity:0.2f options:UIViewAnimationOptionCurveEaseOut animations:^{ fakeContainerView.frame = endFrame; fakeContainerView.backgroundColor = [UIColor eventCellBackground]; overlayView.alpha = 0.0f; } completion:^(BOOL finished) { [fromEventDetailViewController.view removeFromSuperview]; [overlayView removeFromSuperview]; [fakeContainerView removeFromSuperview]; [transitionContext completeTransition:YES]; }]; } 

另一个解决scheme可以使用beginAppearanceTransition:endAppearanceTransition:。 据文件记载:

如果您正在实现自定义容器控制器,请使用此方法告诉孩子其视图即将出现或消失。 不要直接调用viewWillAppear :, viewWillDisappear :, viewDidAppear :,或viewDidDisappear:。

以下是我如何使用它们:

 - (void)animationEnded:(BOOL)transitionCompleted { if (!transitionCompleted) { _toViewController.view.transform = CGAffineTransformIdentity; } else { [_toViewController endAppearanceTransition]; } } - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; [toViewController beginAppearanceTransition:YES animated:YES]; // ... other code } 

但我仍然认为自定义模态演示不会这样做。

经过这个问题多次争论后,我发现在ios7和ios8的最佳解决scheme是离开modalPresentationStyle = UIModalPresentationFullScreen而不是UIModalPresentationCustom作为文档build议。

如果我这样做以及设置transitioningDelegate到我的委托,它仍然尊重我的过渡 will / diddisappear方法在'从'视图控制器调用。 另外:没有现在,然后旋转然后解雇旋转问题启动。

如果使用的是UIModalPresentationCustom ,则应该提供自定义的UIPresentationController类,如果要使用ViewController生命周期调用者,则需要覆盖shouldRemovePresentersView并返回YES

如果您想要保留演示者并仍然具有ViewControlelr生命周期callback,则可以覆盖私有方法_shouldDisablePresentersAppearanceCallbacks并在您的自定义UIPresentationController类中返回NO

啊,这是一个模态演示。 我不相信viewWillAppear和viewDidAppear是使用该方法调用自定义转换,因为视图在技术上仍然在视图层次结构中处于活动状态。 我会build议在这里使用代表团,因为你通常会用一个模式。

在提交的VC上创build委托协议。 创build一个可以从呈现VC调用的委托方法。 在呈现叠加层时,将呈现的VC设置为委托。 然后,从提出的VC调用该委托方法。 然后在调用dismissViewController之前,你可以调用任何types的动作

在你的覆盖(ModalViewController.h)中:

 @protocol ModalViewDelegate <NSObject> -(void)didDismissModalView; @end @interface ModalViewController : UIViewController @property(strong, nonatomic) id <ModalViewDelegate> delegate; 

在你的ModalViewController.m中,调用一个调用你的委托方法的方法:

 - (void)dismissModal{ [self.delegate didDismissModalView]; } 

在你的VC h文件中:(PresentingViewController.h),使这个类符合你的模式委托协议:

 @interface PresentingViewController : UIViewController <ModalViewDelegate> 

在你介绍风险投资时,就像你介绍的那样:

 ... ModalViewController *modalViewController = [[ModalViewController alloc] init]; modalViewController.delegate = self; //the makes the presenting VC the delegate [self presentViewController:modalViewController animated:YES completion:nil]; ... 

最后,在你介绍VC的时候,当你想在解除模态之前执行一些动作的时候,实现ModalViewDelegate方法:

 - (void)didDismissModalView{ //DO SOME COOL STUFF, SET UP STUFF HERE, UPDATE UI, ETC //Then dismiss the modal [self dismissViewControllerAnimated:YES completion:^{ //Do more cool stuff }]; } 

所有这一切都将与您当前的自定义转换代码一起工作,但是会让您更好地控制模式/覆盖被解除之前发生的情况。 代表是一件美丽的事情。

此外,这将保持这个animation代码与其他function的代码分开,这是一个更清洁的国际海事组织。

@John Tracids'anser解决了我的问题。 谢谢约翰!

但是我想稍微回答一下。

如果您使用modalPresentationStyle = .custom (objc UIModalPresentationCustom )呈现UIViewController实例,以便保持viewcontroller的生命周期方法被调用,则必须明确地pipe理viewcontroller的外观。 为了做到这一点,只需在animation完成块中调用beginAppearanceTransition,然后执行animation和endAppearanceTransition

你也可以传递给你的过渡animation师类自定义的UIPresentationController子类重写值shouldRemovePresentersView返回true而不会调用beginAppearanceTransition

// Swift 4

在animation之前把它放到你的自定义的UIViewControllerAnimatedTransitioning类中

 fromViewController.beginAppearanceTransition(false, animated: true) toViewController.beginAppearanceTransition(true, animated: true) UIView.animate(withDuration: animationDuration, animations: { // animation logic… }) { finished in fromViewController.endAppearanceTransition() toViewController.endAppearanceTransition() let transitionSuccess = !transitionContext.transitionWasCancelled transitionContext.completeTransition(transitionSuccess) } // UIPresentationController subclass class PresentationController: UIPresentationController { override var shouldRemovePresentersView: Bool { return true } }