Matt199
Matt199

Reputation: 284

How to fix disappearing Tab Bar Controller when changing View Controller initialized from code

I'm struggling with the problem which is when I'm switching view controllers connected with push segue then everything works as expected. The problem is that I have a search bar that executes Table View Controller from code and when I select the cell from that Table View Controller the next view controller is without tab bar.

I am using Table View Controller as a view that displays results from search bar. When I am selecting cell (result from searching) then I am changing view controller showing the results. But this one is done from storyboard. I know that the Table View Controller executed from code does not "inherits" tab bar from previous controllers through the navigation bar. But this one should be executed from code.

Initialize Search Result Controller
 override func viewDidLoad() {
    super.viewDidLoad()
    self.definesPresentationContext = true

    tableView.separatorStyle = .none
    self.extendedLayoutIncludesOpaqueBars = true
    refreshControlUI = Refresher.configureRefresher()
    tableView.refreshControl = refreshControlUI
    refreshControlUI.addTarget(self, action: #selector(pullToRefresh), for: .valueChanged)


    // Initialize search table
    let priceSearchTable = storyboard?.instantiateViewController(withIdentifier: "CoinSearchTable") as! CoinSearchTableViewController

    // asignle pricetable as a search results controller
    resultSearchController = UISearchController(searchResultsController: priceSearchTable)
    resultSearchController?.searchResultsUpdater = priceSearchTable

    // Make navigation bar large
    self.navigationController?.navigationBar.prefersLargeTitles = true
    self.navigationController?.navigationItem.largeTitleDisplayMode = .never
    self.navigationItem.searchController = resultSearchController

    // customize search bar
    let searchBar = resultSearchController!.searchBar
    searchBar.sizeToFit()
    searchBar.placeholder = "Search for coins"

    resultSearchController?.hidesNavigationBarDuringPresentation = false
    resultSearchController?.dimsBackgroundDuringPresentation = true


 }
This code is responsible just for passing values to selected view controller.
 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    if shownAllCoins.count > 0 {

            let coinString = shownAllCoins[indexPath.row]
            picked = PickedCoin(symbols: [coinString])
            picked.delegate = self
            navigationController?.setNavigationBarHidden(false, animated: true)
            picked.getDetail(name: coinString)
            coin = picked.coins[0]
    }

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if segue.identifier == "goToDetailsFromSearch" {
        if let coin = sender as? [Any]{
            if let SearchVC = segue.destination as? DetailPriceViewController{

                SearchVC.coin = coin[0] as? Coin
                SearchVC.isFromSearching = coin[1] as! Bool
            }
        }

    }
}

Also In Detail View Controller I had to create navigation bar programmatically in case if the segue was from the Search Result Controller.

func addNavBar() {

        view.backgroundColor = UIColor(hex: 0x001f3e)

        let navBar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 20, width: view.frame.size.width, height: 44))
        navBar.barTintColor = UIColor(hex: 0x001f3e)
        navBar.isTranslucent = false
        self.view.addSubview(navBar);
        guard let coin = coin else {return}
        let navItem = UINavigationItem(title: "\(coin.symbol)")

        let backButton = UIButton(type: .custom)
        let textAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white]
        navBar.titleTextAttributes = textAttributes

        saveButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.bookmarks, target: self, action: #selector(self.selectorName(_ :)));


        backButton.setTitle("Back", for: .normal)
        backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
        backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)

        navItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
        navItem.rightBarButtonItem = saveButton

        navBar.setItems([navItem], animated: false)
    }

Bellow is screenshot of storyboard connection. This storyboard without navigation bar is of course this SearchResultController (Table View Controller that displays results and switches to the detail controller).

storyboard expected failed What is the best way to set tab bar as a root controller or something. I just need the tab bar to be in all view controller doesn't matter if the controllers are initialize from storyboard or code.

I am trying all day to fix this but I don't know how.. I appreciate every help!

Thanks!

Upvotes: 1

Views: 1328

Answers (1)

Matt199
Matt199

Reputation: 284

Ok, the problem was with segues. I tried to pass the value from another Controller, that has nothing in common with previous one so that was obvious that navigation bar and tab bar wasn't there. While dealing with separate serchable view controller, there should be added delegation, to pass the vale back to Main Controller. When interacting with searchable view controller, the procedure to pass the value to another view controller in my case looks like this:

  1. When I start typing on my Main Controller the new Searchable View Controller Appear
  2. When I find the item I needed Im selecting it by didSelectedRowAt
  3. I'm Passing the selected value through the delegate function
  4. Added delegate to Main Controller from where should be done segue

Now it works like it supposed to.

The simple code looks like this:

protocol SearchTableDelegate {
func passSelectedValue(selected stock: String) 
}

In Searchable View Controller declare:

var delegate: SearchTableDelegate!

In DidSelectedRowAt:

delegate.passSelectedValue(selected: selectedValue)

Now in Main Controller:

class MainTableViewController: UITableViewController, SearchTableDelegate {...}

And use the function from protocol:

    func passSelectedValue(selected value: String) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    if let destinationVC = storyboard.instantiateViewController(withIdentifier: "details") as? DetailsViewController{
        destinationVC.value = value
        self.navigationController?.pushViewController(destinationVC, animated: true)
    }
}

Also when declaring the SearchableViewController in MainController don't forget to assign delegate from Searchable to self:

searchableTableController.delegate = self

Upvotes: 1

Related Questions