Search code examples
swiftnslayoutconstrainttabbar

Swift - Programmatically refresh constraints


My VC starts with stackView attached with Align Bottom to Safe Area .

I have tabBar, but in the beginning is hidden tabBar.isHidden = true.

Later when the tabBar appears, it hides the stackView

So I need function that refresh constraints after tabBar.isHidden = false


When I start the app with tabBar.isHidden = false the stackView is shown properly.


Tried with every function like: stackView.needsUpdateConstraints() , updateConstraints() , setNeedsUpdateConstraints() without success.


Now I'm changing the bottom programatically, but when I switch the tabBarIndex and return to that one with changed bottom constraints it detects the tabBar and lifts the stackView under another view (which is not attached with constraints). Like is refreshing again the constraints. I'm hiding and showing this stackView with constrains on/off screen.

I need to refresh constraints after tabBar.isHidden = false, but the constraints don't detect the appearance of the tabBar.

As I mention switching between tabBars fixes the issue, so some code executes to detecting tabBar after the switch. Is anyone know this code? I tried with calling the methods viewDidLayoutSubviews and viewWillLayoutSubviews without success... Any suggestions?


Solution

  • This amateur approach fixed my bug... :D

    tabBarController!.selectedIndex = 1
    tabBarController!.selectedIndex = 0
    

    Or with an extension

    extension UITabBarController {
    
        // Basically just toggles the tabs to fix layout issues
        func forceConstraintRefresh() {
        
            // Get the indices we need
            let prevIndex = selectedIndex
            var newIndex = 0
        
            // Find an unused index
            let items = viewControllers ?? []
            find: for i in 0..<items.count {
                if (i != prevIndex) {
                    newIndex = i
                    break find
                }
            }
        
            // Toggle the tabs
            selectedIndex = newIndex
            selectedIndex = prevIndex
        
        }
    
    }
    

    Usage (called when switching dark / light mode):

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        
        tabBarController?.forceConstraintRefresh()
    
    }