2

This is more or less my Main.storyboard situation:

enter image description here

where I have a root UITabBarController with 5 possibile choices. Then, I want that some UIViewControllers can rotate to landscape while I want also some other UIViewControllers to have only landscape mode. So I have written this file.swift:

class CustomNavigationController: UINavigationController, UINavigationControllerDelegate {

  override func shouldAutorotate() -> Bool {
    if (self.topViewController?.isKindOfClass(HomeViewController) != nil) {return false}
    else if (self.topViewController?.isKindOfClass(ServicesViewController) != nil) {return false}
    else if (self.topViewController?.isKindOfClass(PhotoGalleryViewController) != nil) {return false}
    else if (self.topViewController?.isKindOfClass(SelectMapViewController) != nil) {return false}
    else if (self.topViewController?.isKindOfClass(MapViewController) != nil) {return false}
    else {return true}
  }

}

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate {
  override func shouldAutorotate() -> Bool {
    return (self.selectedViewController as! UINavigationController).shouldAutorotate()
  }
}

and I have assigned to all UINavigationControllers the same class CustomNavigationController while I have assigned CustomTabBarController class to UITabBarController. The result is that no view controller do not rotates. Is this because I have assigned the same class to them? Shall I create a custom navigation controller class for each UINavigationController I have?

UPDATE

A partial solution I found, even if it's a little intricate, is the following. I have modified the previous file like that:

class CustomNavigationController: UINavigationController, UINavigationControllerDelegate {

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

}

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate { override func shouldAutorotate() -> Bool { return (self.selectedViewController as! UINavigationController).shouldAutorotate() } }

Then, in view controllers where rotation is allowed I simply have:

override func shouldAutorotate() -> Bool {
    return true
}

while in view controllers where rotation is not allowed I have:

override func shouldAutorotate() -> Bool {
    return false
}

override func viewWillAppear(animated: Bool) {
    let value = UIInterfaceOrientation.Portrait.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")
}

Anyway there's a little problem because the animation which sets mode to portrait is not correct meaning that the width of the screen is not adjusted. if I go from a landscape view controller to a portrait only view controller then the view controller frame is not correct. I get

enter image description here

instead of this:

enter image description here

SagittariusA
  • 5,289
  • 15
  • 73
  • 127

1 Answers1

1

Try this in AppDelegate

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if let rootController = self.window?.rootViewController as? UITabBarController {
        if let navigationController = rootController.selectedViewController as? UINavigationController {
            let controller = navigationController.topViewController!

            if controller.isKindOfClass(HomeViewController.classForCoder()) {
                return UIInterfaceOrientationMask.Portrait
            }
            if controller.isKindOfClass(ServicesViewController.classForCoder()) {
                return UIInterfaceOrientationMask.Portrait
            }
            if controller.isKindOfClass(PhotoGalleryViewController.classForCoder()) {
                return UIInterfaceOrientationMask.Portrait
            }
            if controller.isKindOfClass(SelectMapViewController.classForCoder()) {
                return UIInterfaceOrientationMask.Portrait
            }
            if controller.isKindOfClass(MapViewController.classForCoder()) {
                return UIInterfaceOrientationMask.Portrait
            }
        }
    }
    return UIInterfaceOrientationMask.All
}

Update:

This method forces application to change orientation in ViewController that should be only in Portrait (HomeViewController, ServicesViewController, PhotoGalleryViewController, SelectMapViewController, MapViewController):

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    let value = UIInterfaceOrientation.Portrait.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
Sasha Kozachuk
  • 1,283
  • 3
  • 14
  • 21
  • Thank you for your suggestion but I am afraid it does not work...they all rotate with no exception :( – SagittariusA Mar 31 '16 at 09:00
  • @LoryLory sorry I have edited my answer. Previous worked only with Presented controller. This one should work. Also, it will work even without CustomNavigationController. Try it ;) – Sasha Kozachuk Mar 31 '16 at 09:10
  • ok it works but now I have the problem described in my question update: if I go from a landscape view controller to a portrait only view controller then the view controller frame is not correct. Se the new images. – SagittariusA Mar 31 '16 at 09:15
  • @LoryLory For that you need to add one more line of code in HomeViewController, ServicesViewController, PhotoGalleryViewController, SelectMapViewController, MapViewController. Check out answer – Sasha Kozachuk Mar 31 '16 at 09:19
  • what you wrote is exactly the same code I added in my viewWillAppear() but the "transformation" is not right...I get that strage image as if the table view remains in landscape mode. I have tried to update its frame too but id does not change – SagittariusA Mar 31 '16 at 09:22
  • it could be a auto layout bug as they say here: http://stackoverflow.com/questions/14307037/bug-in-uitableview-layout-after-orientation-change – SagittariusA Mar 31 '16 at 09:24
  • Try to play with attributes of View Controller where that table view is. Like "Should Adjust Scroll View Insets" – Sasha Kozachuk Mar 31 '16 at 09:33
  • I have added `self.automaticallyAdjustsScrollViewInsets = true` to `viewWillAppear()` but neither this works :( – SagittariusA Mar 31 '16 at 09:39
  • remove all func shouldAutorotate() methods, that's what prevents your controller from rotating back to Portrait. Leave only viewViwllAppear and main method in AppDelegate – Sasha Kozachuk Mar 31 '16 at 09:43
  • sorry...nothing to do. I removed all `shouldAutorotate()` methods and custom class navigation controller and custom class tab bar controller. I just have `viewWillAppear()` like you wrote it... but it's useless. It looks so silly all this, it would be supposed to be such a simple thing... – SagittariusA Mar 31 '16 at 09:51