Search code examples
iosswiftdelegatescontainerscontainer-view

Delegate is nil when using container views


I have 2 Container Views which have a UITableViewController(sideMenuVC) and a UICollectionViewController(centerVC) embedded inside respectively and my CollectionVC is inside a navigation controller itself. I have put these two Container Views inside a third VC which is the rootVC. Now I am trying to show content in my centerVC based on the row that is selected in the sideMenuVC and I am using delegates, however, the delegate is nil when I try to call it from the sender. I have tried setting the delegate as weak and also setting the delegate in awakeFromNib instead of viewDidLoad, I have also tried to set the delegate from different VCs.

Here is my protocol:

import Foundation
import Photos

protocol sideMenuDelegate {
    func handleRowSelection(title: String, fetchResult: PHFetchResult<PHAsset>, assetCollection: PHAssetCollection?)
}

and this is how I set the delegate inside the third VC which holds both Container Views:

let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
sideMenuVC = storyboard.instantiateViewController(withIdentifier: "sideVC") as? SideMenuViewController
centerVC = storyboard.instantiateViewController(withIdentifier: "centerVC") as? centerViewController
sideMenuVC?.delegate = centerVC

I have also tried setting it in my centerVC like so:

let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
sideMenuVC = storyboard.instantiateViewController(withIdentifier: "sideVC") as? SideMenuViewController
sideMenuVC?.delegate = self

and finally this is the implementation of the delegate func:

extension centerViewController: sideMenuDelegate {
    func handleRowSelection(title: String, fetchResult: PHFetchResult<PHAsset>, assetCollection: PHAssetCollection?) {
        pageTitle = title
        inFetchResult = fetchResult
        inAssetCollection = assetCollection
    }  
}

I think the problem is with accessing the correct instance of VCs from the storyboard but I couldn't find any way to fix it.


Solution

  • I have found the solution.

    When using Container Views, the correct way of getting references to the embedded VCs is to implement Prepare for segue method and access the destination property inside the VC class that contains the Container Views; like so:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if segue.identifier == "sideVCSeg" {
                sideMenuVC = (segue.destination as! SideMenuViewController)
            }
            if segue.identifier == "centerVCSeg" {
                let navController = (segue.destination as! UINavigationController)
                centerVC = (navController.viewControllers.first as! centerViewController)
            }
        }
    

    and because this method is executed when the view is loading I only had to add this line to viewDidLoad :

    sideMenuVC?.delegate = centerVC