0

I am now pulling my hair out trying to resolve what I thought would be a simple function. I am using Xcode 6.2 to create an iOS 8 app for the iPad with 3 view controllers. My aim is once the app is launched, it locks all the views in that Landscape orientation. If it’s closed and reopened in the other Landscape orientation, all views use that. I did get this working with code below but have had to add a navigation controller because I need a Navigation Bar and it now always rotates. I have found some information that this maybe a bug in iOS8. Suggestions I have tried haven’t resolved problem as the are Object-C, this was interesting but as its not for swift I am lost.

iOS 6 shouldAutorotate: is NOT being called

Is there a simple way to accomplish this by forcing the Navigation Controller to stop rotation? Here is a snippet which used to work and the Lock screen code is in each VC:-

        // Get orintation of screen if 'true' Home button on RIGHT
        if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft) {
            Oriention_Number = HomeButtonRight
            Screen_Orient_Vert = -1
            Screen_Orient_Horiz = 1
        } else {
            Oriention_Number = HomeButtonLeft
            Screen_Orient_Vert = 1
            Screen_Orient_Horiz = -1
        }
        preferences.setInteger(Oriention_Number, forKey: "Oriention_Number_Prefs")


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

override func supportedInterfaceOrientations() -> Int {
    return Oriention_Number // Landscape HomeButtonLeft = 16 HomeButtonRight = 8
}
Community
  • 1
  • 1
Andy
  • 107
  • 1
  • 8
  • I updated Xcode & Swift to 1.2 and added original code in root view controller and it now all works correctly. // Lock Screen override func shouldAutorotate() -> Bool { return false } – Andy May 07 '15 at 06:35

2 Answers2

1

Subclass UINavigationController:

class LandscapeNC2:UINavigationController {
    override func supportedInterfaceOrientations() -> Int {
    var s:UIInterfaceOrientationMask = .LandscapeRight
    let o:UIDeviceOrientation = UIDevice.currentDevice().orientation
    if (o == .LandscapeRight) || (o == .PortraitUpsideDown) { s = .LandscapeLeft }
        return Int(s.rawValue)
    }
}

Does that work? I've not tested it.

You need to change the definition of you UINavigationController to be a LandscapeNC2. The controller which determines the rotation capability is the rootmost one of the set of controllers that currently cover the entire screen. If you have a UINavigationController, that's usually the one that determines the rotation.

You will find that the supportedInterfaceOrientations methods of the VCs managed by the UINavigationController are never called. That's because when they are on screen, the tab bar of the UINavigationController is on screen too, and that is further towards the root of the stack of VCs.

emrys57
  • 6,679
  • 3
  • 39
  • 49
  • Thanks for your quick reply and suggestion, I tried yours first because it was for swift. I added the Class and code you suggested to root navigation controller (initial VC) and it works correctly in all my views but I need to find orientation of app when its launched, then lock it. I added my code that gets the orientation (snippet above) but it has already locked screen as your code is run first. Also the Launch screen doesn't have your orientation only the first main VC, can these be solved please? – Andy Mar 30 '15 at 18:11
  • Thanks emrys57 but I must be doing something wrong. I added suggested code & print statement:-println("s = \(s.rawValue)") return Int(s.rawValue) The Navigation Controller has the Class LandscapeNC2 set but when its run I get the outputs shown below. Why does it loop so many times & after Main VC launched? Homebutton Left:- s=16 s=16 s=16 s=16 s=16 Its launched 36 (println in main VC) s=8 s=8 s=8 s=8 s=8 Result:- Lunch screen & all VC’s correct. Homebutton Right:- s=16 s=16 s=16 s=16 s=16 s=16 Its launched 37 s=16 s=16 s=16 s=16 s=16 s=16 Result:- Lunch screen OK but all VC’s upside-down. – Andy Mar 31 '15 at 09:45
  • I updated the answer to turn it the other way up. The routine is called by iOS, I wouldn't worry about how often it is called. – emrys57 Mar 31 '15 at 11:39
  • Tried this version but neither orientation locks now. So to confirm previous code locked once MyVC reached (not launch screen) homebutton Left correctly but homebutton right opens MyVC upside down. – Andy Mar 31 '15 at 12:33
1

By UINavigationController doesn't pass shouldAutorotate calls to its children. Add a category for UINavigationController (or subclass it), and implement the following:

- (BOOL)shouldAutorotate
{
  return [self.topViewController shouldAutorotate];
}

This will then use your existing shouldAutorotate logic.

James Frost
  • 6,960
  • 1
  • 33
  • 42
  • Thanks for the suggestion but I am new to swift so could you please explain what swift code I should add and where. – Andy Apr 07 '15 at 19:20