Let’s study this example: every time you rotate your iPad, you need to recalculate cell heights in your table view. You only need to do this on iPad, because iPhone version of the app is going to have only portrait orientation.
So, we need to detect orientation change. Once orientation change is detected we can call tableView.reloadData() method. Let’s code.
First of all, we need to add an observer to our view controller. Add this line in viewDidLoad() method:
1 |
NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) |
Also, implement rotated() method.
1 2 3 |
func rotated() { } |
You only need to detect orientation change between two orientations: Landscape and Portrait. But there are a couple more device orientations. We also have FaceUp and FaceDown orientations. We don’t want to reload data in table view every time we go from, say, Landscape to FaceUp, because in that case the interface orientation shouldn’t change.
Also, if we change orientations like this:
Portrait – FaceUp – Portrait
we don’t want to reload table view. So, when we go from FaceUp to Portrait again, we need to know that the last orientation that counts was Portrait also. To store the last orientation we need a variable.
Create this variable in your view controller:
1 |
var lastOrientation:UIDeviceOrientation! |
Instantiate it in viewDidLoad():
1 |
lastOrientation = UIDevice.current.orientation |
Now we can rewrite rotated() method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
func rotated(){ guard UIDevice.current.userInterfaceIdiom == .pad else{ //we need to reload table only on iPad. return } let currentOrientation = UIDevice.current.orientation guard UIDeviceOrientationIsLandscape(currentOrientation) || UIDeviceOrientationIsPortrait(currentOrientation) else { // we are only interested in Portrait and Landscape orientations return } guard currentOrientation != lastOrientation else { //remember the case of Portrait-FaceUp-Portrait? Here we make sure that in such cases we don't reload table view return } lastOrientation = currentOrientation tableView.reloadData() //finally, when we know that orientation did actually change, we reload table view } |
So, that’s how it is done. Or at least how I did it in my Stream Journal app. I wonder if it is the best possible way to detect change between Portrait and Landscape. What if, instead of device orientation change, we could detect user interface orientation change directly? That would save us all the additional coding. If you know of such a way, please, comment.
Here is something free for you
Don’t close this page yet. Before you go, maybe you’d like to check out my app. If you want to control your life and be focused on your goals this app is definitely for you. You create your own list of questions and then answer those questions every day. And recently I added the ability to create multiple lists of questions.
I think your solution is working but it is not a good practice to rely on NotificationCenter, you should make a proper xib or storyboard with constraints, available for each orientation and then check orientation changes with viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)