在segue期间何时初始化目标视图控制器?

时间:2016-09-13 08:14:44

标签: ios swift uiviewcontroller segue uistoryboardsegue

我试图编写一个协议和一个自定义的UIStoryboardSegue类,它允许我在UIViewControllers中轻松实现自定义转换:

public protocol TransitionController
{
    var transitionDurationIn:  CFTimeInterval { get }
    var transitionDurationOut: CFTimeInterval { get }
    func prepareTransitionIn()
    func prepareTransitionOut()
    func performTransitionIn(finished: @escaping () -> Void)
    func performTransitionOut(finished: @escaping () -> Void)
}

class JFTransitionControllerSegue: UIStoryboardSegue {
    override func perform() {
        let defaultTransitionDuration : CFTimeInterval = 1.5

        if let dvc = self.destination as? TransitionController {
            dvc.prepareTransitionIn()
        }
        else {
            // Default transition
            self.destination.view.alpha = 0
        }
        if let svc = self.source as? TransitionController {
            svc.prepareTransitionOut()
            svc.performTransitionOut(){ () in
                if let dvc = self.destination as? TransitionController {
                    dvc.performTransitionIn(){ () in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
                else {
                    // Default transition for the destination controller
                    UIView.animate(withDuration: defaultTransitionDuration, animations: {
                        self.destination.view.alpha = 1
                    }) { (Finished) in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
            }
        }
        else
        {
            // Default transition for the source controller
            UIView.animate(withDuration: defaultTransitionDuration, animations: {
                self.source.view.alpha = 0
            }) { (Finished) in
                if let dvc = self.destination as? TransitionController {
                    dvc.performTransitionIn(){ () in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
                else {
                    // Default transition for the destination controller
                    UIView.animate(withDuration: defaultTransitionDuration, animations: {
                        self.destination.view.alpha = 1
                    }) { (Finished) in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
            }
        }
    }
}

class TestController: UIViewController, TransitionController {
    @IBOutlet weak var form_username: UITextField!

    // MARK: - TransitionController Protocol

    var transitionDurationIn  : CFTimeInterval {return 1.0}
    var transitionDurationOut : CFTimeInterval {return 1.0}

    func prepareTransitionIn()
    {
        //self.view.alpha = 0 // no fade in if you uncomment
        form_username.alpha = 0 // nil
    }
    func prepareTransitionOut()
    {
        self.view.alpha = 1 // works
    }
    func performTransitionIn(finished: @escaping () -> Void)
    {
        UIView.animate(withDuration: self.transitionDurationIn, animations: {
            //self.view.alpha = 1 // no fade in if you uncomment
            self.form_username.alpha = 1 // nil, crashes
        }) { (Finished) in
            finished()
        }
    }
    func performTransitionOut(finished: @escaping () -> Void)
    {
        UIView.animate(withDuration: self.transitionDurationOut, animations: {
            self.view.alpha = 0 // fades out correctly
        }) { (Finished) in
            finished()
        }
    }
}

基本上,您只需在任何您想要的UIViewController中实现协议,然后创建类JFTransitionControllerSegue的segue。在performTransitionIn函数中,您可以执行UIView.animate之类的操作,并更改alpha或您喜欢的任何内容。我遇到的问题是目标segue只是弹出而不是正确转换。从我在调试时可以看出它没有完全初始化 - IBOutlet变量是零,但控制器本身不是。这是一个糟糕的设计模式,还是我只是遗漏了一些简单的东西?

2 个答案:

答案 0 :(得分:1)

正在初始化的视图控制器是一个事件。它被加载的视图是另一个。

视图控制器的view属性是懒惰加载的,并且在此处构建并连接了出口。这就是viewDidLoad()为什么的原因。

如果您希望视图为您做好准备,可以先在视图控制器上调用loadViewIfNeeded()

答案 1 :(得分:0)

误解了问题...目标控制器已加载,但我忘记将目标控制器的视图添加到Segue类的窗口中:

class JFTransitionControllerSegue: UIStoryboardSegue {
    override func perform() {
        let defaultTransitionDuration : CFTimeInterval = 1.5

        if let dvc = self.destination as? TransitionController {
            dvc.prepareTransitionIn()
        }
        else {
            // Default transition
            self.destination.view.alpha = 0
        }
        if let svc = self.source as? TransitionController {
            svc.prepareTransitionOut()
            svc.performTransitionOut(){ () in

                UIApplication.shared.keyWindow?.insertSubview(self.destination.view, aboveSubview: self.source.view)
                if let dvc = self.destination as? TransitionController {
                    dvc.performTransitionIn(){ () in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
                else {
                    // Default transition for the destination controller
                    UIView.animate(withDuration: defaultTransitionDuration, animations: {
                        self.destination.view.alpha = 1
                    }) { (Finished) in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
            }
        }
        else
        {
            // Default transition for the source controller
            UIView.animate(withDuration: defaultTransitionDuration, animations: {
                self.source.view.alpha = 0
            }) { (Finished) in
                UIApplication.shared.keyWindow?.insertSubview(self.destination.view, aboveSubview: self.source.view)
                if let dvc = self.destination as? TransitionController {
                    dvc.performTransitionIn(){ () in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
                else {
                    // Default transition for the destination controller
                    UIView.animate(withDuration: defaultTransitionDuration, animations: {
                        self.destination.view.alpha = 1
                    }) { (Finished) in
                        self.source.present(self.destination, animated: false, completion: nil)
                    }
                }
            }
        }
    }
}