将以编程方式创建的视图连接到IB

时间:2019-03-02 22:28:42

标签: swift uipresentationcontroller

在回答this之后,我设法将ViewControllerB的半峰形式添加到ViewControllerA中。但是,在示例中,ViewControllerA只是一个红色视图。我想将其连接到IB以便对其进行自定义。我尝试在类ViewControllerB的IB中创建一个视图控制器,并将其视图之一连接到@IBOutlet var menuView: UIView!,而不是通过编程方式创建menuView(如示例中所示)。但是,将nil作为子视图添加到视图时发现menuView。任何帮助都会很棒。谢谢!

1 个答案:

答案 0 :(得分:0)

一些观察结果:

  1. 在该示例中,有一行显示:

    let vc = ViewControllerB()
    

    您可以在NIB中定义该视图控制器的视图,这样可以很好地工作。但是,如果您使用情节提要,请将其替换为...

    let vc = storyboard!.instantiateViewController(withIdentifier: “identifier")
    

    ...其中identifier是您在IB的“身份检查器”中为该场景提供的一些字符串,作为“故事板ID”。

  2. 如果这是由按钮或类似的东西触发的,则您也可以在该示例中删除此gotoVCB,然后像往常一样在IB中进行模态表示(例如 control -从按钮拖动到下一个场景),然后选择“模态呈现”。但是您必须确保配置了所有init方法,例如:

    class ViewControllerB: UIViewController {
    
        // used if you use NIBs or just call `init()`
    
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
            super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
            configure()
        }
    
        // used if you use storyboards
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            configure()
        }
    
        private func configure() {
            modalPresentationStyle = .custom
            transitioningDelegate = self
        }
    
        ...
    }
    
  3. 与紧迫的问题无关,我建议将that answer’s代码拆分为单独的对象,以防止视图控制器“膨胀”,并更好地将过渡的委托对象,动画控制器等之间的职责分开

    例如,也许:

    class ViewControllerB: UIViewController {
    
        let customTransitioningDelegate = PopUpMenuTransitioningDelegate()
    
        override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
            super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
            configure()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            configure()
        }
    
        func configure() {
            modalPresentationStyle = .custom
            transitioningDelegate = customTransitioningDelegate
        }
    
    }
    

    class PopUpMenuTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
        func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return PopUpMenuAnimationController(transitionType: .presenting)
        }
    
        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return PopUpMenuAnimationController(transitionType: .dismissing)
        }
    }
    

    class PopUpMenuAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
        enum TransitionType {
            case presenting
            case dismissing
        }
    
        let transitionType: TransitionType
    
        init(transitionType: TransitionType) {
            self.transitionType = transitionType
            super.init()
        }
    
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 1
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            let containerView = transitionContext.containerView
            guard let toVC = transitionContext.viewController(forKey: .to),
                let fromVC = transitionContext.viewController(forKey: .from) else { return }
    
            switch transitionType {
            case .presenting:
                containerView.addSubview(toVC.view)
    
                var rect = fromVC.view.bounds
                let menuHeight = fromVC.view.bounds.height / 2
                rect.origin.y += fromVC.view.bounds.height
                rect.size.height = menuHeight
                toVC.view.frame = rect
                toVC.view.alpha = 0
    
                UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
                    rect.origin.y = menuHeight
                    toVC.view.frame = rect
                    toVC.view.alpha = 1
                }, completion: { _ in
                    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                })
    
            case .dismissing:
                UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
                    var rect = fromVC.view.frame
                    rect.origin.y = toVC.view.bounds.height
                    fromVC.view.frame = rect
                    fromVC.view.alpha = 0
                }, completion: { _ in
                    transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
                })
            }
        }
    }
    

    这将过渡的委托和动画控制器与视图控制器分离,并允许您在需要时将其与其他视图控制器一起使用。

    注意,我对completeTransition的参数也要多加注意。一旦开始使用交互式过渡,您可能会支持可取消的过渡。