2

I'm trying to adjust some views when the iPhone changes it's orientation from portrait to landscape and vice versa. Everything works fine on iOS8 but unfortunately the changes aren't animated, but happen immediately, on iOS9. Here is the code that I have in a modal UIViewController presented via a custom transition:

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

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.AllButUpsideDown
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return .Portrait
}

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    let changeToPortrait = size.width < size.height
    coordinator.animateAlongsideTransition({ (context) -> Void in
        //show portrait
        if changeToPortrait {
            //do view changes...
        }

        //show landscape
        else {
            //undo view changes...
        }
    }) { (context) -> Void in
        print("done")
    }
}

If I print coordinator.isAnimated() it says false and therefore the coordinator.transitionDuration() is also 0.0.

What do I have to do to animate the transition changes?

Thanks for your help!

Hannes
  • 3,752
  • 2
  • 37
  • 47

2 Answers2

3

This behavior is likely because you set a custom UIWindow subclass to the window property of the AppDelegate inside the application:didFinishLaunchingWithOptions: method, as telomere mentioned in another answer.

If you need to use a UIWindow subclass in iOS 9, implement a custom getter for the window property of the AppDelegate to maintain orientation change animations.

Apple's documentation for UIApplicationDelegate's window property says:

"...you must implement the getter method of this property and use it to create and return your custom window."

Common practice is often to set the window property directly in application:didFinishLaunchingWithOptions:. Instead, in your AppDeleate, implement the custom getter like this (Thanks to Tomas Camin for the code, found here):

Objective-C

- (MyCustomWindow *)window
{    
    static MyCustomWindow *customWindow = nil;
    if (!customWindow) customWindow = [[MyCustomWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    return customWindow;
}

Swift

var customWindow: MyCustomWindow?    
var window: UIWindow? {
    get {
        customWindow = customWindow ?? MyCustomWindow(frame: UIScreen.mainScreen().bounds)
        return customWindow
    }
    set { }
}
Community
  • 1
  • 1
adamup
  • 1,508
  • 19
  • 29
  • Doesn't even need to be with a UIWindow subclass. I was creating a UIWindow instance manually because of GCKUICastContainerViewController and was having this problem. The Swift solution worked for me. – tmagalhaes Oct 19 '17 at 19:56
2

Have a look at your application:didFinishLaunchingWithOptions: handler. It seems that if you manually create your application's UIWindow object, this triggers the iOS9 rotation issue.

I'm not sure of the exact reason, but in our app we were able to fix the issue by removing the code which manipulated the UIWindow and instead let the storyboard system initialise it.

telomere
  • 338
  • 3
  • 10