2

My App has a TabBarViewController containing 4 tabs. One of the tabs is Settings which I want to move to a separate storyboard. If I am only consider iOS 9 and above as my deployment target, then I can just refactor the SettingsTab using Storyboard Reference. However I want to target iOS 8 as well. Since Storyboard Reference doesn't support Relationship Segue, I can't rely on it in this case.

So in the main storyboard which contains the TabBarViewController, I keep a dummy SettingsTabViewController as an empty placeholder. And in the function "viewWillAppear" in its class file, I push the view to the real SettingsTabViewController in the Settings.storyboard. This works fine. But the problem is if I keep tabbing the Settings tab, the empty placeholder view controller will show up for a short time and then goes back to the real Settings view.

I tried to implement this delegate to lock the Settings tab:

func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {

      return viewController != tabBarController.selectedViewController

}

However, the other three tabs were locked too after I implemented this delegate.

Is it possible to just lock the Settings tab without locking other three tabs? And in which view controller exactly should I implement this delegate?

TunaTheDog
  • 33
  • 6

1 Answers1

1

Yes, it's possible. You need to check the index; with the following code not only you can prevent locking other tabs, but also you still have tap on tab goto root view controller feature.

func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {
    let tappedTabIndex = viewControllers?.indexOf(viewController)
    let settingsTabIndex = 3 //change the index
    if tappedTabIndex == settingsTabIndex && selectedIndex == settingsTabIndex {
        guard let navVC = viewController as? UINavigationController else { return true }
        guard navVC.viewControllers.count > 1 else { return true }

        let firstRealVC = navVC.viewControllers[1]
        navVC.popToViewController(firstRealVC, animated: true)
        return false
    }
    return true
}

.

This answers your question, but still you would have the settingsVC showing up for a moment. To avoid this you simply need to turn off the animation while you're pushing it. so you need to override viewWillAppear in the following way.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    if let theVC = storyboard?.instantiateViewControllerWithIdentifier("theVC") {
        navigationController?.pushViewController(theVC, animated: false)
    }
}

after adding above code you still would see a back button in your real first viewController. You can hide it:

override func viewDidLoad() {
    super.viewDidLoad()
    navigationItem.hidesBackButton = true
}
Erfan
  • 143
  • 10