UIViewControllerTransitioningDelegate方法未在iOS 7中调用

时间:2015-10-05 22:45:53

标签: ios objective-c iphone

我通过实现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

在模态视图控制器中(即&#34;呈现的控制器&#34;)我在其-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];

4 个答案:

答案 0 :(得分:48)

如果有人在以后的几年遇到过这种情况,并且您使用的是Swift 3,请确保您的通话至&#34; animationControllerForPresentedController& #34;

从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

答案 1 :(得分:9)

另一个问题是transitioningDelegate is a weak property。因此,您可以分配给它,然后在转换有机会运行之前让您的转换委托类已发布。当转换 运行时,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")
}

在过渡之前查看该print语句是否被点击。

如果您使用独立类来实现UIViewControllerTransitioningDelegate,则会遇到此问题。这就是为什么诸如this one之类的教程通常会在视图控制器类本身或扩展中实现转换委托的原因。其他的事情是让视图控制器不被释放。

一般来说,在Cocoa Touch中,任何名为“... Delegate”的东西都是弱属性,以帮助避免保留周期。您还应该使自己的自定义类委托属性变弱。在Apple的Cocoa Core Competencies中有一个很好的部分。

答案 2 :(得分:2)

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

在iOS 7中,视图控制器的转换逻辑在viewDidLoad之前调用,但从iOS 8开始是另一种方式。

答案 3 :(得分:0)

挖掘后,我发现我的 transitioningDelegate 方法没有被调用,因为它们是在协议扩展中实现的,并且委托方法必须是协议扩展中不支持的@objc。 我的解决方案是将其移动到具体类中并添加@objc 标记

    @objc func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        ...


    }
    
    // interaction for dismissing from  view
    @objc func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
   ...   
   }