簡體   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