繁体   English   中英

UIViewControllerTransitioningDelegate 方法未在 iOS 7 中调用

[英]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是一个弱属性 所以你可以分配给它,然后在转换有机会运行之前释放你的转换委托类。 当过渡运行,值transitioningDelegatenil ,你的方法永远不会被调用。

要查看这一点,请执行以下操作:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM