[英]UIViewControllerTransitioningDelegate methods not called
[英]UIViewControllerTransitioningDelegate method not called in iOS 7
我通过实现UIViewControllerTransitioningDelegate
协议中的方法为模态视图控制器创建了自定义过渡动画。
在 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.
}
并记得在要呈现的 View Controller 上设置呈现样式:
self.modalPresentationStyle = .custom
和代表:
self.transitioningDelegate = self // or wherever
另一个问题是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”的东西都将是一个弱属性,以帮助避免保留循环。 您也应该使自己的自定义类委托属性变弱。 在 Apple 的Cocoa Core Competencies 中有一个很好的部分。
在呈现视图控制器的初始化程序中设置transitioningDelegate
而不是viewDidLoad
方法解决了这个问题。
它出现在 iOS 7 中,在viewDidLoad
之前调用了视图控制器的转换逻辑,但从 iOS 8 开始则相反。
挖掘后,我发现我的 transitioningDelegate 方法没有被调用,因为它们是在协议扩展中实现的,并且委托方法必须是协议扩展中不支持的@objc。 我的解决方案是将其移动到具体类中并添加 @objc 标记
@objc func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
...
}
// interaction for dismissing from view
@objc func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.