简体   繁体   中英

Animate parent VC object from a child VC

Is it possible to animate views of a parent VC in Swift?

I've got a root/master VC with a UIView which I'm using as a sort of a UITabBarController, so the rest of my 4 main VCs are children of the root.

On some of the child VCs, I have subviews that should take up the whole screen, without seeing the custom tab bar (UIView) from the root VC, but it still floats above.

I would like to have it slide off the screen via Y axis whenever I open the fullscreen subviews, but I can't seem to access or manipulate the root VCs properties as it returns nil on runtime.

Here's the custom tab bar root VC so you can understand the structure of the code:

class RootVC: UIViewController {

    //This is where we pull all of our content from other VCs
    //when a tab bar button is selected
    @IBOutlet weak var contentView: UIView!

    //The custom tab bar itself with an array of button outlets
    @IBOutlet public weak var customTabBarContainer: UIView!
    @IBOutlet var tabBarButtons: [UIButton]!

    //4 main view VCs that are reflected in the tab bar
    public var mapVC: UIViewController!
    public var favoritesVC: UIViewController!
    public var chatVC: UIViewController!
    public var profileVC: UIViewController!

    //Array for the VCs above
    public var viewControllers: [UIViewController]!

    //Index of the selected button determend by their tags
    public var selectedIndex: Int = 0

    @IBOutlet weak var loadingLogo: UIImageView!

    override public func viewDidLoad() {
        //Populating viewControllers array with
        //initiated VCs in Main storyboard
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        mapVC = storyboard.instantiateViewController(withIdentifier: "MapVC")
        favoritesVC = storyboard.instantiateViewController(withIdentifier: "FavoritesVC")
        chatVC = storyboard.instantiateViewController(withIdentifier: "ChatVC")
        profileVC = storyboard.instantiateViewController(withIdentifier: "ProfileVC")
        viewControllers = [mapVC, favoritesVC, chatVC, profileVC]

        //Custom tab bar + buttons visual properties
            customTabBarContainer.layer.cornerRadius = customTabBarContainer.frame.height / 2
            customTabBarContainer.layer.shadowColor = UIColor.darkGray.cgColor
            customTabBarContainer.layer.shadowOffset = CGSize.zero
            customTabBarContainer.layer.shadowRadius = 10
            customTabBarContainer.layer.shadowOpacity = 0.9
            tabBarButtons[0].imageView?.contentMode = .scaleAspectFit
            tabBarButtons[1].imageView?.contentMode = .scaleAspectFit
            tabBarButtons[2].imageView?.contentMode = .scaleAspectFit
            tabBarButtons[3].imageView?.contentMode = .scaleAspectFit

    }


    override public func viewDidAppear(_ animated: Bool) {
        loadingLogo.popOut()
        //Loads the initial VC
        contentView.addSubview(mapVC.view)
        mapVC.view.frame = self.view.frame
        mapVC.didMove(toParentViewController: self)
        customTabBarContainer.isHidden = false
        //Selects the inital home button
        tabBarButtons[0].isSelected = true
    }


    @IBAction func didTabButton(_ sender: UIButton) {

        //Keeps a track of which bar button is selected
        let previousIndex = selectedIndex
        selectedIndex = sender.tag

        //Deselects the previous bar button
        tabBarButtons[previousIndex].isSelected = false

        //Removes the previous VC
        let previousVC = viewControllers[previousIndex]
        previousVC.view.removeFromSuperview()
        previousVC.removeFromParentViewController()

        print("switced to \(viewControllers[selectedIndex])")

        //Selects the tapped bar button
        tabBarButtons[selectedIndex].isSelected = true
        tabBarButtons[selectedIndex].popIn()

        //Brings up the selected VC
        let nextVC = viewControllers[selectedIndex]
        contentView.addSubview(nextVC.view)
        nextVC.view.frame = self.view.frame
        nextVC.didMove(toParentViewController: self)

    }
}

And here's the code I'm trying to use to manipulate the customTabBarContainer from a child of the MapVC:

    UIView.animate(withDuration: 0.4, animations: {

        let root = self.parent?.parent as! RootVC
        root.customTabBarContainer.frame.origin.y -= root.customTabBarContainer.frame.height

    }, completion: nil)

why are you trying to access the parent of the parent then?

self.parent?.parent as RootVC

assuming you are using an extension like this one to find your parentVC:

extension UIView {
    var parentViewController: UIViewController? {
        var parentResponder: UIResponder? = self
        while parentResponder != nil {
            parentResponder = parentResponder!.next
            if parentResponder is UIViewController {
                return parentResponder as! UIViewController!
            }
        }
        return nil
    }
} 

you should be able to access parent via

let root = self.parentViewController as! RootVC

I've figured out an answer, just in case anyone else encounters a similar problem. It will not take you to the VCs immediate parent, but instead, to its most distant ancestor, which solves my particular problem in this case.

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let rootVC = appDelegate.window?.rootViewController as! RootVC
    rootVC.customTabBarContainer.isHidden = true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM