Mohammed Yaseen Shah
Mohammed Yaseen Shah

Reputation: 35

How do I keep my viewWillTransition to one view controller and not all?

Here is how I'm overriding my view controllers, however, if there is another better way to do it and make it so my second view controller does not conform to the override please direct me to it, any advice would be good.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {


    coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in

        let orient = UIApplication.shared.statusBarOrientation

        switch orient {
        case .portrait:
            print("Portrait")
            self.applyPortraitConstraint()
            break
        // Do something
        default:
            print("LandScape")
            // Do something else
            self.applyLandScapeConstraint()
            break
        }
    }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
        print("rotation completed")
    })
    super.viewWillTransition(to: size, with: coordinator)
}

 func applyPortraitConstraint(){
    stackView.axis = .vertical
    stackView.distribution = .fill
}

 func applyLandScapeConstraint(){
    stackView.axis = .horizontal
    stackView.distribution = .fillEqually
}

Upvotes: 2

Views: 2544

Answers (4)

Greg
Greg

Reputation: 707

Expanding on droptic54's excellent answer, if you just want each tab controller to run its own transition code but not any of the others', you can use .selectedViewController instead of .selectedIndex == 0 (or whichever index):

'guard self == self.tabBarController?.selectedViewController else { return }`

If you decide later to change the tab order, you won't have to worry about which tab has which index

Upvotes: 0

Wolfshead
Wolfshead

Reputation: 550

A better version of the guard statement would be:

guard
    tabBarController?.selectedViewController === self
else {
    return
}

So that you don't pollute your view controller implementation with the order in which you populate the tabs.

Upvotes: 2

droptic54
droptic54

Reputation: 81

Although you've found a way to work around the issue you had I thought I'd provide a simpler way to handle it. Another bonus is that it will be less fragile in that it will work no matter what views are in your controller.

First, a little context partly based on info already included in the comments for Malik's answer: As Malik points out, the "viewWillTransition" method will only get executed in the view controllers which include it. But since you're using a tab bar controller, each of the controllers associated with the tab bar stay in existence even when you are on a different tab. So, even if the user is on a different tab controller when you rotate the device, the "viewWillTransition" method will still get called in the controller which has the method. So, what if you want the code in that method to execute only if the user is currently on that tab?

Here's a simpler solution: If you want the code that is currently in "viewWillTransition" to be called only when the user is on that controller's tab, you can add a guard statement before that code which checks the current value of "tabBarController.selectedIndex". The "selectedIndex" value tells you what tab controller is currently selected and visible.

For example, suppose "viewWillTransition" is in the tab controller whose index is 0. You can include a guard statement that checks that the selectedIndex is 0, and if not, just returns. This will prevent the rest of the code in the method from being executed if the user isn't currently on tab 0. If the user is on the tab with an index of 1 and rotates the device, although "viewWillTransition" will still get called in Controller 0, the guard statement will prevent the rest of the code from being executed.

Here's the code:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        guard tabBarController?.selectedIndex == 0 else { return }
        //Include the rest of your code here
}

Hope this helps you or someone else!

Upvotes: 8

Malik
Malik

Reputation: 3802

As per my understanding, this code will only work in the viewController that it is a part of. Any other viewController will not be calling this method. Instead, they will be calling their own method. I don't see how other viewControllers would be able to use this piece of code. Unless you are using the same code in all your viewControllers in which case, I would recommend to only use this code in the viewControllers that you actually want to follow this behaviour.

Upvotes: 1

Related Questions