永远不会调用交互式代理方法

编程入门 行业动态 更新时间:2024-10-21 13:08:58
本文介绍了永远不会调用交互式代理方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想在ViewController(1)和NavigationViewController(2)之间进行交互式转换。

I want to make an interactive transition between a ViewController (1) and a NavigationViewController (2).

NavigationController由一个按钮调用,因此在呈现时没有交互式转换。它可以通过按钮或UIPanGestureRecognizer来解除,因此它可以被交互或不被解雇。

The NavigationController is called by a button, so there's no interactive transition when presenting. It can be dismissed by a button or a UIPanGestureRecognizer, so it can be dismissed interactively or not.

我有一个名为TransitionManager的对象,用于转换,UIPercentDrivenInteractiveTransition的子类。

I have an object named TransitionManager for the transition, subclass of UIPercentDrivenInteractiveTransition.

以下代码的问题是从不调用两个委托方法 interactionControllerFor ... 。

The problem with the code below is that the two delegate methods interactionControllerFor... are never called.

此外,当我按下按钮或swip(UIPanGestureRecognizer)时,模态segue的基本动画就完成了。所以两个委托方法 animationControllerFor ... 也不起作用。

Moreover, when I press the buttons or swip (UIPanGestureRecognizer), the basic animation of the modal segue is done. So the two delegate methods animationControllerFor... don't work either.

任何想法?谢谢

let transitionManager = TransitionManager() override func viewDidLoad() { super.viewDidLoad() self.transitioningDelegate = transitionManager } override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { let dest = segue.destinationViewController as UIViewController dest.transitioningDelegate = transitionManager dest.modalPresentationStyle = .Custom }

TransitionManager.swift

TransitionManager.swift

class TransitionPushManager: UIPercentDrivenInteractiveTransition, UINavigationControllerDelegate, UIViewControllerTransitioningDelegate { @IBOutlet var navigationController: UINavigationController! var animation : Animator! // Implement UIViewControllerAnimatedTransitioning protocol override func awakeFromNib() { var panGesture = UIPanGestureRecognizer(target: self, action: "gestureHandler:") navigationController.view.addGestureRecognizer(panGesture) animation = Animator() } func gestureHandler(pan : UIPanGestureRecognizer) { switch pan.state { case .Began : interactive = true navigationController.presentingViewController?.dismissViewControllerAnimated(true, completion:nil) case .Changed : ... default : ... interactive = false } } func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return animation } func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return animation } func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return nil } func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return self.interactive ? self : nil }

Main.storyboard

  • ViewController上的按钮触发了一个模态segue来呈现NavigationController

    Main.storyboard

    • The button on the ViewController triggered a modal segue to presenting the NavigationController

      NavigationController的委托出口链接到TransitionManager类的对象

      The NavigationController's delegate outlet is linked to an object of the TransitionManager class

      NavigationController在属性navigationController中引用了TransitionController

      The NavigationController is referenced in the TransitionManager class by the property "navigationController"

      推荐答案

      我认为关键问题是你正在配置 transitionDelegate in viewDidLoad 。在这个过程中,这通常太晚了。您应该在 init 导航控制器时执行此操作。

      I think the key problem is that you're configuring the transitionDelegate in viewDidLoad. That's often too late in the process. You should do it as you init the navigation controller.

      让我们想象您的根场景(Root)呈现导航控制器场景(导航),然后从场景A推送到B到C,例如,我想象一个像这样的对象模型,导航控制器将只拥有自己的动画控制器,交互控制器,和手势识别器:

      Let's imagine your root scene ("Root") that presents the navigation controller scene ("Nav"), that then pushes from scene A to B to C, for example, I'd imagine an object model like this, where the navigation controller would simply own its own animation controller, interaction controller, and gesture recognizer:

      当考虑到(a)root呈现nav时的自定义转换(非交互式)时,这就是你所需要的; (b)当nav自行解散以返回根时的自定义转换(交互与否)。所以,我将导航控制器子类化:

      This is all you need when considering (a) a custom transition (non-interactive) when "root" presents "nav"; and (b) a custom transition (interactive or not) when "nav" dismisses itself in order to return to the "root". So, I'd subclass the navigation controller which:

      • 在其视图中添加手势识别器;

      • adds a gesture recognizer to its view;

      设置 transitioningDelegate ,以便在从根场景转换到导航控制器场景(并返回)时生成自定义动画:

      sets the transitioningDelegate to yield the custom animation as you transition from the root scene to the navigation controller scene (and back):

      transitioningDelegate 还将返回交互控制器(只有在手势识别器处于此状态时才会存在)如果你在手势的上下文之外解散,则在手势和非交互式转换期间产生交互式转换。

      the transitioningDelegate will also return the interaction controller (which will only exist while the gesture recognizer is in progress), yielding interactive transition during gesture and non-interactive transition if you dismiss outside of the context of the gesture.

      在Swift 3中,它看起来像:

      In Swift 3, that looks like:

      import UIKit import UIKit.UIGestureRecognizerSubclass class CustomNavigationController: UINavigationController { public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) configure() } override init(rootViewController: UIViewController) { super.init(rootViewController: rootViewController) configure() } private func configure() { transitioningDelegate = self // for presenting the original navigation controller } override func viewDidLoad() { super.viewDidLoad() delegate = self // for navigation controller custom transitions let left = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(handleSwipeFromLeft(_:))) left.edges = .left view.addGestureRecognizer(left) } fileprivate var interactionController: UIPercentDrivenInteractiveTransition? func handleSwipeFromLeft(_ gesture: UIScreenEdgePanGestureRecognizer) { let percent = gesture.translation(in: gesture.view!).x / gesture.view!.bounds.size.width if gesture.state == .began { interactionController = UIPercentDrivenInteractiveTransition() if viewControllers.count > 1 { popViewController(animated: true) } else { dismiss(animated: true) } } else if gesture.state == .changed { interactionController?.update(percent) } else if gesture.state == .ended { if percent > 0.5 && gesture.state != .cancelled { interactionController?.finish() } else { interactionController?.cancel() } interactionController = nil } } } // MARK: - UINavigationControllerDelegate // // Use this for custom transitions as you push/pop between the various child view controllers // of the navigation controller. If you don't need a custom animation there, you can comment this // out. extension CustomNavigationController: UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { if operation == .push { return ForwardAnimator() } else if operation == .pop { return BackAnimator() } return nil } func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return interactionController } } // MARK: - UIViewControllerTransitioningDelegate // // This is needed for the animation when we initially present the navigation controller. // If you're only looking for custom animations as you push/pop between the child view // controllers of the navigation controller, this is not needed. This is only for the // custom transition of the initial `present` and `dismiss` of the navigation controller // itself. extension CustomNavigationController: UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return ForwardAnimator() } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return BackAnimator() } func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return interactionController } func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return interactionController } func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return PresentationController(presentedViewController: presented, presenting: presenting) } } // When doing custom `present`/`dismiss` that overlays the entire // screen, you generally want to remove the presenting view controller's // view from the view hierarchy. This presentation controller // subclass accomplishes that for us. class PresentationController: UIPresentationController { override var shouldRemovePresentersView: Bool { return true } } // You can do whatever you want in the animation; I'm just fading class ForwardAnimator : NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.5 } func animateTransition(using context: UIViewControllerContextTransitioning) { let toView = context.viewController(forKey: .to)!.view! context.containerView.addSubview(toView) toView.alpha = 0.0 UIView.animate(withDuration: transitionDuration(using: context), animations: { toView.alpha = 1.0 }, completion: { finished in contextpleteTransition(!context.transitionWasCancelled) }) } } class BackAnimator : NSObject, UIViewControllerAnimatedTransitioning { func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.5 } func animateTransition(using context: UIViewControllerContextTransitioning) { let toView = context.viewController(forKey: .to)!.view! let fromView = context.viewController(forKey: .from)!.view! context.containerView.insertSubview(toView, belowSubview: fromView) UIView.animate(withDuration: transitionDuration(using: context), animations: { fromView.alpha = 0.0 }, completion: { finished in contextpleteTransition(!context.transitionWasCancelled) }) } }

      所以,我可以将故事板中我的导航控制器的基类更改为这个自定义子类,现在根场景可以只出现导航控制器(没有特殊的 prepare(for :)),一切正常。

      So, I can just change the base class of my navigation controller in the storyboard to be this custom subclass, and now the root scene can just present the navigation controller (with no special prepare(for:)) and everything just works.

更多推荐

永远不会调用交互式代理方法

本文发布于:2023-11-26 20:57:40,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1635167.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:永远不会   方法

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!