Marco
Marco

Reputation: 1077

iOS: rotation issues with supportedInterfaceOrientations()

I'm building an app in swift using the storyboard. It's composed by a UITabBarController, a UINavigationController and threeUIViewController`.

TabBarController -> NavigationController -> ViewController1 -> VC2 -> VC3

I want to structure the app so that the first 2 view controller can be only in Portrait and the third can be only in LandscapeRight.

I create a subclass for the UITabBarController:

class OrientationTab: UITabBarController {

    override func shouldAutorotate() -> Bool{
        if self.selectedViewController != nil{
            if self.selectedViewController.respondsToSelector("shouldAutorotate") {
                println("TAB - shouldAutorotate - inside if")
                return self.selectedViewController.shouldAutorotate()
            }
         }
         println("TAB - shouldAutorotate - outside if")
         return true
     }

     override func supportedInterfaceOrientations() -> Int{
         if self.selectedViewController != nil{
             if self.selectedViewController.respondsToSelector("supportedInterfaceOrientations"){
                 println("TAB - supportedInterfaceOrientations - inside if")
                 return self.selectedViewController.supportedInterfaceOrientations()
             }
         }
         println("TAB - supportedInterfaceOrientations - outside if")
         return Int(UIInterfaceOrientationMask.All.rawValue)
     }

and for the UINavigationController:

class OrientationNav: UINavigationController {

    override func shouldAutorotate() -> Bool{
        if self.topViewController.respondsToSelector("shouldAutorotate") {
            println("NAV - shouldAutorotate - if")
            return self.topViewController.shouldAutorotate()
        }else{
            println("NAV - shouldAutorotate - else")
            return true
        }
   }

   override func supportedInterfaceOrientations() -> Int{
        if self.topViewController.respondsToSelector("supportedInterfaceOrientations"){
             println("NAV - supportedInterfaceOrientations - if")
             return self.topViewController.supportedInterfaceOrientations()
        }else{
             println("NAV - supportedInterfaceOrientations - else")
             return Int(UIInterfaceOrientationMask.All.rawValue)
        }
   }

in the custom ViewController I add this methods:

override func shouldAutorotate() -> Bool{
    // This method is the same for all the three custom ViewController
    return true
}

override func supportedInterfaceOrientations() -> Int{
    // Portrait for the first 2 ViewController
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
    // LandscapeRight for the third
    return Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)
}

When I launch the application the first two ViewController are blocked in Portrait, the third instead of being in LandscapeRight orientation is in Portrait mode. Only if I rotate the device into LandscapeRight the interface rotate to the correct position. How Can I solve this problem?

Also, when I try to return at the second ViewController of the navigationBar using the BackButton the page remain blocked and I receive this error: Unbalanced calls to begin/end appearance transitions for <_TtC11AppNamem6Detail: 0x145ab3a0>.

Upvotes: 4

Views: 7734

Answers (3)

D Lindsey
D Lindsey

Reputation: 131

Swift 3 will need these to be var and not func types.

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .all
}

Upvotes: 1

cheborneck
cheborneck

Reputation: 61

In the child viewController you specify what orientations you want to support:

override func supportedInterfaceOrientations() -> Int
{
    // designate we only like to be in landscape mode
    return UIInterfaceOrientationMask.Landscape.rawValue.hashValue
}

In the navigationController (root) you specify if it can rotate based on the child view controller:

override func shouldAutorotate() -> Bool 
{
    return self.topViewController.shouldAutorotate()
}

then in the child view controller you set if it should rotate:

override func shouldAutorotate() -> Bool
{
    // tells the root view controller we don't want to be reoriented
    return false
}

This will stop the desired view from rotating.

Then if you want to force it into a specific orientation then you set...

override func viewWillAppear(animated: Bool)
{
    // when the view controller appears rotate it to landscape mode
    UIApplication.sharedApplication().setStatusBarOrientation(UIInterfaceOrientation.LandscapeRight, animated: true)
}

Upvotes: 2

SomeProgrammerGuy
SomeProgrammerGuy

Reputation: 9

According to a lot of research on this same issue. Some resources state that all view controllers must be the same mode. You cannot have one different from the others when using UINavigationController.

Upvotes: 0

Related Questions