在iOS 7中不调用UIViewControllerTransitioningDelegate方法

我通过实现UIViewControllerTransitioningDelegate协议中的方法为模式视图控制器创build了自定义的过渡animation。

在iOS 8和9中,这些方法通常被调用并且转换工作。 但是,在iOS 7中, animationControllerForPresentedController:presentingController:sourceController:方法永远不会被调用。 animationControllerForDismissedController:方法仍然正常调用。

 #import "MyModalTransitioningDelegate.h" #import "MyModalFadeTransition.h" @implementation MyModalTransitioningDelegate - (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { return [[MyModalFadeTransition alloc] init]; } - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { return [[MyModalFadeTransition alloc] init]; } @end 

在模式视图控制器(即“呈现的控制器”),我有以下在它的-viewDidLoad方法:

 self.modalTransitionDelegate = [[OTModalTransitioningDelegate alloc] init]; // This is a custom strong private property due to `tranisitioningDelegate` being a weak property. self.transitioningDelegate = self.modalTransitionDelegate; self.modalPresentationStyle = UIModalPresentationCustom; 

设置modalPresentationStyle在iOS的任何版本中似乎没有任何区别。 没有被调用的方法确实说它在iOS 7中可用,所以我不知道为什么它不被调用。

模态视图控制器在呈现视图控制器中呈现以下代码:

 [self presentViewController:self.modalViewController animated:YES completion:nil]; 

如果任何人在晚些时候遇到这个,并且你正在使用Swift 3,请确保你的调用不是animationControllerForPresentedController ”。

从Xcode 8.1开始,编译器不会自动识别这个问题,因此不会将代码转换为现代语法。

上面的代码将被编译,但不会是一个协议实现。 这将只是一个自定义的 ,未被调用的函数。 (这是可选协议方法的危害,以及Xcode自动完成的无数问题。)

所以,确保你用Swift 3语法来实现协议:

 func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { // ... return your cached controller object here. } 

并记住要设置视图控制器上的演示文稿样式:

 self.modalPresentationStyle = .custom 

和代表:

 self.transitioningDelegate = self // or wherever 

在呈现视图控制器的初始化程序而不是viewDidLoad方法中设置transitioningDelegate修复了问题。

它出现在iOS 7中,视图控制器的转换逻辑在viewDidLoad之前被调用,但是从iOS 8开始反过来。

另一个问题是, transitioningDelegate是一个弱财产 。 所以你可以分配它,然后在转换有机会运行之前释放你的转换委托类。 当过渡运行时,transitioningDelegate的值是nil ,并且你的方法永远不会被调用。

要查看此信息,请执行以下操作:

 let myVC = UIViewController(nibName: nil, bundle: nil) likesVC.transitioningDelegate = BackgroundFadesInPresentationDelegate(viewController: likesVC) likesVC.modalPresentationStyle = .custom present(likesVC, animated: true, completion: nil) 

然后在你的转换委托类中添加

 deinit { print("deinit") } 

看看这个打印语句是否在转换之前被击中。

如果您使用独立类来实现UIViewControllerTransitioningDelegate则会遇到此问题。 这就是为什么像这样的教程通常需要在视图控制器类本身或作为扩展实现转换委托。 其他的事情是让视图控制器得到释放。

一般来说,在Cocoa Touch中,任何名为“… Delegate”的东西都是一个弱的属性,有助于避免保留周期。 您应该使自己的自定义类委托属性也很弱。 在苹果的cocoa核心能力方面,有一个很好的部分。