0

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.

HemOdd
  • 697
  • 1
  • 7
  • 23
  • I suspect your final sentence may be correct. Do you do anything to connect the `sideMenuVC` object to the view controller hierarchy after creating the instance...or is that being done through regular storyboard loading? – Phillip Mills Mar 16 '19 at 20:26
  • No. I have set up everything in the storyboard and I am just using the given code to get the instance initiated via storyboard which is not working. I couldn't find any other code for this purpose. – HemOdd Mar 16 '19 at 20:34
  • I can't give much detail from what I'm seeing but what you need to do is not instantiate anything new. You should instead be making the delegate connection by getting references to the correct controllers when they are loaded by the storyboard. Or...can you set the delegate connection inside the storyboard? – Phillip Mills Mar 16 '19 at 20:47
  • Connecting using storyboard is not working so I am trying to do it via code. Do you know any other code that might work? – HemOdd Mar 16 '19 at 21:34
  • and by using storyboard I mean setting the delegate property as IBOutlet and connecting it by control+dragging. – HemOdd Mar 16 '19 at 21:42

1 Answers1

0

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
HemOdd
  • 697
  • 1
  • 7
  • 23