Search code examples
iosswiftuicollectionviewuisegmentedcontrolchildviewcontroller

Swift iOS -Adding ChildViewController to CollectionView Section using SegmentedControl


I have a view controller that contains a collectionView with 2 sections. The header of the second section is a sticky header and it has a segmentedControl inside of it:

ParentViewController
    --collectionView
         --sectionOne // because there is specific data in sectionOne I cannot use a PageViewController
         --sectionTwo
           sectionTwoHeader // sticky header
           [RedVC, BlueVC, GreenVC] // these should be the size of sectionTwo

When a segment is selected I'm using a ContainerVC that will show a view controller corresponding to each segment:

// each of of these color vcs have collectionViews inside of them
RedCollectionViewController(), BlueCollectionViewController(), GreenCollectionViewController()

The problem is when the segment is selected the collectionView isn't showing any of the color view controllers it's supposed to show. How do I add each color vc using addChildViewController() to a collectionView?

The collectionView w/ segmentedControl's selectedIndex:

class ParentViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{

    var collectionView: UICollectionView!
    var containerController: ContainerController!
    var vc: UIViewController!

    override func viewDidLoad() {
        super.viewDidLoad()
        containerController = ContainerController()
    }

    @objc func selectedIndex(_ sender: UISegmentedControl){

        let index = sender.selectedSegmentIndex

        switch index {
        case 0:
            containerController.vcIdentifierReceivedFromParent(segment: "BlueVC")
            break
        case 1:
            containerController.vcIdentifierReceivedFromParent(segment: "RedVC")
            break
        case 2:
            containerController.vcIdentifierReceivedFromParent(segment: "GreenVC")
            break
        default: break
       }

        /*
        // because of the X and Y values this adds the containerVC over the collectionView instead of under the sectionTwo segmented Control header 
        vc = containerController
        addChildViewController(vc)
        vc.view.frame = CGRect(x: 0,y: 0, width: collectionView.frame.width,height: collectionView.frame.height)
        view.addSubview(vc.view)
        vc.didMove(toParentViewController: self)
        lastViewController = vc
        */
    }
}

ContainerVC:

class ContainerController: UIViewController {

var vc: UIViewController!
var lastViewController: UIViewController!

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white
    vcIdentifierReceivedFromParent(segment: "RedVC")
}

func vcIdentifierReceivedFromParent(segment: String){

    switch segment {

    case "RedVC":

        let redVC = RedCollectionViewController()
        addVcToContainer(destination: redVC)
        break

    case "BlueVC":

        let blueVC = BlueCollectionViewController()
        addVcToContainer(destination: blueVC)
        break

    case "GreenVC":

        let greenVC = GreenCollectionViewController()
        addVcToContainer(destination: greenVC)
        break

    default: break
    }
}

func addVcToContainer(destination: UIViewController) {

        //Avoids creation of a stack of view controllers
        if lastViewController != nil{
            lastViewController.view.removeFromSuperview()
        }

        self.vc = destination
        addChildViewController(vc)
        vc.view.frame = CGRect(x: 0,y: 0, width: view.frame.width,height: view.frame.height)
        view.addSubview(vc.view)
        vc.didMove(toParentViewController: self)
        lastViewController = vc
    }
}

Solution

  • You are adding Red / Blue / Green VCs to Container View controller that is referenced from inside ParentViewController. But you are adding each of them inside ContainerVC topmost view, whose frame is probably never set, as far as I can see from your code.

    It's probably CGRectZero.

    Adding child VC views to this view will result in they are getting wrongly positioned, or not positioned at all. Because Container View controller is nowhere in the view controller hierarchy. You are effectively doing everything within ParentViewController's viewDidLoad(). Most probably, ContainerVC's viewDidLoad is not even called. Hence its view is never initialised properly.

    You probably do not need ContainerVC at all. Try adding children to ParentViewController, and try adding them after viewDidLoad() call, i.e. in viewDidAppear(), viewDidLayoutSubviews() and upon switch segment selection.