Search code examples
swifttableviewcollectionview

TableView inside a CollectionView crashes the app


I am building a multi screen app which uses a UICollection view to navigate between UIViewControllers. The left one is green and the right is red. Swiping left or right brings you to the ViewController. It works, but when I add a TableViewController to the green one, the app crashes. I added all outlets. It says:

SwipeViewController[11639:3937203] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file SwipeViewController/GreenViewController.swift, line 21

which points to tableViewI.delegate = self.

Here is the CollectionView code:

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
@IBOutlet var collectionView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    
    collectionView.backgroundColor = .yellow
    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionViewCell")
    collectionView.isPagingEnabled = true
    collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .centeredVertically, animated: false)
    
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 2
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath)
    //cell.backgroundColor = indexPath.item % 2 == 0 ? .purple : cell.backgroundColor
    switch indexPath.row {
    case 0:
        self.addChild(GreenViewController())
        cell.contentView.addSubview(GreenViewController().view)
    case 1:
        self.addChild(RedViewController())
        cell.contentView.addSubview(RedViewController().view)
    default:
        print("nothing")
    }
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: self.view.frame.width, height: self.view.frame.height)
}

And here the green ViewController containing the tableView:

class GreenViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tableViewI: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = .green
    tableViewI.delegate = self
    tableViewI.dataSource = self
    tableViewI.register(UINib.init(nibName: "cellID", bundle: nil), forCellReuseIdentifier: "cellID")
    
    }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cellID") as! TableViewCell
    cell.backgroundColor = .blue
    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

Solution

  • The problem is how you are creating the object of GreenViewController class.

    You must load it from the storyboard instead of just creating it from the init method of GreenViewController. Otherwise, outlet properties will be nil.

    let vc = storyboard?.instantiateViewController(withIdentifier: "yourIdentifier") as! GreenViewController