0

Since the problem is hard to explain, here is a video attached.

The behavior above happens when I select a cell on a table view controller and it performs a segue to a tab bar controller. During the transition, I rotate the device to landscape mode and if done fast enough, the tab bar will disappear and the view will load on half of the screen and the other half stays black.

I did this in my app and I thought I was doing something wrong, so I made a new app with the same structure but no view controllers and this happens too.

I noticed, if the perform segue is not animated, this bug won't appear but I want the animation. I believe that delaying the screen rotation until the view has loaded will fix the problem.

Here is the storyboard

Nathan Barreto
  • 365
  • 2
  • 21

1 Answers1

0

Is there a way to lock rotation until the view has loaded?

Yes there is. But before we proceed to that, since I saw your video/issue, usually when needed, a view must be re-layouted. Not sure about the term, but you can adjust its constraints based on the current orientation.

Anyways, for the way to lock the rotation until you want it be unlocked, I've found this utility quite long time ago.

import UIKit

struct AppUtility {

    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {

        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }
    }

    /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {

        self.lockOrientation(orientation)

        UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    }

}

This has been very helpful to me. Now to use it, it's no brainer.

class ViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        // Lock immediately the rotation to portrait!
        // Use lockOrientationAndRotateTo if it's needed.

        AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // Then finally, after loading something, enable rotation.

        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) {

            // Assuming that the loading takes 5 seconds or so.

            AppUtility.lockOrientation(.all)
        }
    }
}

Good luck! I hope this helps!

Glenn Posadas
  • 12,555
  • 6
  • 54
  • 95
  • Just to be sure, I have to add the orientationLock variable to AppDelegate, right? – Nathan Barreto Mar 22 '18 at 16:49
  • Anywhere you need it. You can add it in the AppDelegate if the your issue shows up in the first screen. Let me know if this helps. – Glenn Posadas Mar 23 '18 at 07:41
  • I implemented but it didn't work. I believe there is something(maybe a function) missing in app delegate that locks the orientation. I searched and found this - func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return self.orientationLock } – Nathan Barreto Mar 23 '18 at 14:01
  • I see that your answer refers to [this answer](https://stackoverflow.com/questions/28938660/how-to-lock-orientation-of-one-view-controller-to-portrait-mode-only-in-swift). Adding those missing codes, it worked for me. – Nathan Barreto Mar 23 '18 at 14:17
  • Awesome. If this is the only answer that helped you out, you can close this question by selecting this as an answer (you can change it in the future). – Glenn Posadas Mar 23 '18 at 16:59