swiftuianimation

Swift - Flipping view controllers disables IBOutlets


My app starts and I'm presenting VC1 on the top of tabBarController

tabBarController?.present(VC1, animated: false, completion: nil)

It presents first page and I have another page VC2. I make flip transition between these 2 pages by posting notification to the current opened VC0 in the tabBarController(not the presented one, but the one who is in index 0 in the tabBarController).The notifications triggers:

    if var topController = UIApplication.shared.keyWindow?.rootViewController {
        while let presentedViewController = topController.presentedViewController {
            topController = presentedViewController
        }
        let VC2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "VC2") as! VC2
        UIView.transition(from: topController.view, to: VC2.view, duration: 0.85, options: [.transitionFlipFromLeft])
    }

This makes the flip, but it looks like the IBOutlets are not connected and the click is not detected.


Solution

  • You haven't keep any reference if VC2. So IBOutlet's action do not perform. You can try this example. It may be helpful for you.

    ViewController.swift

    import UIKit
    
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        @IBAction func gotoNextPage(_ sender: Any) {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "SecondViewController")
            GlobalVariable.transitionViewFrom(from: self, to: vc, subtype: nil, options: [.transitionFlipFromLeft])
        }
    }
    
    class GlobalVariable: NSObject {
        private static var sharedManager: GlobalVariable!
        public var allViewInstantController: [UIViewController]=[UIViewController]()
        public static let NUMBER_OF_VIEWCONTROLLER_OPEN_AT_A_TIME:Int = 5
    
        static func shared() -> GlobalVariable {
            if(sharedManager==nil){
                sharedManager=GlobalVariable()
            }
            return sharedManager
        }
        override private init() {
        }
    
        static func transitionViewFrom(from:UIViewController, to:UIViewController, subtype:CATransitionSubtype? = nil, options: UIView.AnimationOptions? = nil) -> Void {
            let timeDelay:Double=0.5
            GlobalVariable.checkPreviousView(_view:to)
            GlobalVariable.splashViewFrom(from: from, to:to, isAdd:true, subtype:subtype, options: options, timeDelay: timeDelay)
        }
    
        static func checkPreviousView(_view:UIViewController) -> Void {
            GlobalVariable.shared().allViewInstantController.append(_view)
            if(GlobalVariable.shared().allViewInstantController.count>GlobalVariable.NUMBER_OF_VIEWCONTROLLER_OPEN_AT_A_TIME){
                let myViewController = GlobalVariable.shared().allViewInstantController.first
                myViewController?.view.removeFromSuperview()
                GlobalVariable.shared().allViewInstantController.removeFirst()
            }
        }
    
        static func splashViewFrom(from:UIViewController, to:UIViewController, isAdd:Bool, subtype:CATransitionSubtype? = nil, options: UIView.AnimationOptions? = nil, timeDelay:Double) -> Void {
            do {
                if let subtype = subtype {
                    let transition = CATransition()
                    transition.duration = 0.25
                    transition.isRemovedOnCompletion = true;
                    transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut)
                    transition.type = CATransitionType.push
                    transition.subtype  = subtype
                    from.view.layer.add(transition, forKey: kCATransition)
                }else if let options = options {
                    UIView.transition(from: from.view, to: to.view, duration: timeDelay, options: options)
                }
    
                if(!isAdd){
                    from.view.removeFromSuperview()
                    if(GlobalVariable.shared().allViewInstantController.count>0){
                        GlobalVariable.shared().allViewInstantController.removeLast()
                    }
                }else{
                    if subtype != nil {
                        from.view.addSubview(to.view)
                    }
                }
            }
        }
    
        static func dismissViewFrom(viewController:UIViewController, subtype:CATransitionSubtype) -> Void {
            let timeDelay=0.5
            GlobalVariable.splashViewFrom(from: viewController, to: UIViewController(), isAdd:false, subtype:subtype, timeDelay: timeDelay)
        }
    }
    

    SecondViewController.swift

    import UIKit
    
    class SecondViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
        @IBAction func previousPage(_ sender: Any) {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")
            GlobalVariable.transitionViewFrom(from: self, to: vc, subtype: nil, options: [.transitionFlipFromLeft])
        }
    }
    

    For flip just change type. And change accordingly for back page transaction.

    transition.type = CATransitionType(rawValue: "flip")
    

    Another solution, you can try this.

    ViewController.swift

    import UIKit
    
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            GlobalVariable.shared().rootViewController=self
        }
        @IBAction func gotoNextPage(_ sender: Any) {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "SecondViewController")
            UIView.transition(from: self.view, to: vc.view, duration: 0.5, options: [.transitionFlipFromLeft])
        }
    }
    
    class GlobalVariable: NSObject {
        private static var sharedManager: GlobalVariable!
        public var rootViewController: UIViewController?
        static func shared() -> GlobalVariable {
            if(sharedManager==nil){
                sharedManager=GlobalVariable()
            }
            return sharedManager
        }
        override private init() {
        }
    }
    

    SecondViewController.swift

    import UIKit
    
    class SecondViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            GlobalVariable.shared().rootViewController=self
        }
    
        @IBAction func previousPage(_ sender: Any) {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")
            UIView.transition(from: self.view, to: vc.view, duration: 0.5, options: [.transitionFlipFromLeft])
        }
    }