Show UICollectionView within UITableViewController in Swift

Solution for Show UICollectionView within UITableViewController in Swift
is Given Below:

for a couple days now I been trying to get this working. I want to show a UICollectionView within a UITableViewController class. I have a searchbar to filter for items, but when I dismiss the searchbar, I want the collectionview to appear. I have included my entire code, maybe someone of you can help me to get this to work .. I tried calling func configureCollectionView at different places, but none of them seem to work. All the Cells I am registering are perfectly working (I know so, because they work in other controllers ..)

Thanks!!

 private let reuseIdentifier = "SearchThisCell"

class SearchController: UITableViewController, UISearchBarDelegate, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {


var item1 = [Item1]()
var searchbar = UISearchBar()
var filteredItem = [Item1]()
var inSearchMode = false
var collectionView: UICollectionView!
var collectionViewEnabled = true
var item2 = [Item2]()

override func viewDidLoad() {
    super.viewDidLoad()
    
    // register cell classes
    tableView.register(SearchThisCell.self, forCellReuseIdentifier: reuseIdentifier)

    tableView.separatorInset = UIEdgeInsets(top: 0, left: 75, bottom: 0, right: 75)
    tableView.separatorStyle = .none
    
    configureSearchBar()
    
    configureCollectionView()
    
    fetchItem1()
    
    fetchItem2()
            
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 70
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if inSearchMode {
        return filteredItem.count
    } else {
        return item1.count
    }
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
    var item: Item1!
    
    if inSearchMode {
        item = filteredItem[indexPath.row]
    } else {
        item = item1[indexPath.row]
    }
            
    let itemProfileVC = ItemProfileController(collectionViewLayout: UICollectionViewFlowLayout())
    
    itemProfileVC.item = item
    
    navigationController?.pushViewController(itemProfileVC, animated: true)
    
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! SearchThisCell
    
    var item: Item1!
    
    if inSearchMode {
        item = filteredItem[indexPath.row]
    } else {
        item = item1[indexPath.row]
    }
    
    cell.item = item1
    
    return cell
}

func configureCollectionView() {
    
    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical

    let frame = CGRect(x: 50, y: 50, width: view.frame.width, height: view.frame.height - (tabBarController?.tabBar.frame.height)! - (navigationController?.navigationBar.frame.height)!)

    collectionView = UICollectionView(frame: frame, collectionViewLayout: layout)
    collectionView.delegate = self
    collectionView.dataSource = self
    collectionView.alwaysBounceVertical = true
    collectionView.backgroundColor = .white
    collectionView.register(SearchThatCell.self, forCellWithReuseIdentifier: "SearchThatCell")

    tableView.addSubview(collectionView)
    tableView.separatorColor = .clear
    
}

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

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

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

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchThatCell", for: indexPath) as! SearchThatCell
    
    cell.that = item2[indexPath.item]
    
    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
    let overviewVC = OverviewController(collectionViewLayout: UICollectionViewFlowLayout())
    
    overviewVC.viewSingleItem = true
    
    overviewVC.that = item2[indexPath.item]
    
    navigationController?.pushViewController(overviewVC, animated: true)
    
}

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    searchbar.showsCancelButton = true
    
    collectionView.isHidden = false
    collectionViewEnabled = true
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    
    let searchText = searchText.lowercased()
    
    if searchText.isEmpty || searchText == " " {
        inSearchMode = false
        tableView.reloadData()
    } else {
        inSearchMode = true
        filteredItem = item.filter({ (item) in
            return item.itemname.contains(searchText)
        })
        tableView.isHidden = false
        tableView.reloadData()
    }
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchbar.endEditing(true)
    
    searchbar.showsCancelButton = false
    
    inSearchMode = false
    
    searchbar.text = nil
    
    collectionViewEnabled = true
            
    configureCollectionView()

    tableView.isHidden = true
    
    tableView.reloadData()
}

and then come the fetch functions, which are working as they supposed to.

You’re adding the collection view to the table view. If you hide the table view, all subviews will be hidden as well. Add the collectionview to the view of the controller instead.

change

tableView.addSubview(collectionView)

to

view.addSubview(collectionView)

It would be easier to handle both (table and collectionview) in a normal view Controller.

It’s better to create table cell with collection view inside.