Rotation methods deprecated, equivalent of 'didRotateFromInterfaceOrientation'?
Asked Answered
U

7

142

I'm trying to implement the new viewWillTransitionToSize method which has been introduced in iOS 8 (all other rotation methods have been deprecated). I'd like to know what the equivalent of didRotateFromInterfaceOrientation is now as there are a number of clean up tasks we need to perform and I can't see a block that we can assign to UIViewControllerTransitionCoordinator in order to be called when 'transition' to a new size finishes. Thanks.

Upanddown answered 5/6, 2014 at 22:49 Comment(0)
U
263

Okay found it, just have to use the animateAlongsideTransition:completion: method on the passed UIViewControllerTransitionCoordinator.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{   
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        // do whatever
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    { 

    }];

    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
Upanddown answered 5/6, 2014 at 23:45 Comment(11)
Will this method call every time we rotate like didRotateFromInterfaceOrientation?. Can you please share me the method you have used. Thank youTinea
Yes it will. This is what I do: - (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; // do whatever } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { }]; [super viewWillTransitionToSize: size withTransitionCoordinator: coordinator]; }Upanddown
@strange: Thats great. It would be nice if you could add the code snippet in the answer itself. It looks congested in the commentThickknee
@strange: I have another problem in iOS 8. I have a universal iOS application. This should support all the orientations in iPads and only portrait (home button down) in iPhones. But we need one particular view controller to be locked in landscape mode only in both iPads and iPhones. And once you navigate out of that view controller, it should again support the old orientations. How to achieve this? Please help.Thickknee
Thanks - i'll add a swift version as an answer to save people some timeExchange
Is there a way to remove the animation?Ofay
it will call when you press power button and minimize the app.Illuminism
Holy hell, Apple make it hard, don't they? If it wasn't for Stack Overflow contributors such as yourself, I doubt anyone would make anything of substantial worth with the iOS APIs. It's an absolute mess at this point.Overhear
even having this "[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; " at the bottom makes differenceKainite
statusbarorientation is deprecated in iOS 9. What else is the option?Higherup
@DeepakSharma I'm a little late to the party, but you can use [UIDevice currentDevice].orientation. You can also pipe this into UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation) or UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation). Hope this helps!Sternway
E
72

The Swift Version of the answer by strange

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

    coordinator.animateAlongsideTransition({ (UIViewControllerTransitionCoordinatorContext) -> Void in

        let orient = UIApplication.sharedApplication().statusBarOrientation

        switch orient {
        case .Portrait:
            println("Portrait")
            // Do something
        default:
            println("Anything But Portrait")
            // Do something else
        }

        }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
            println("rotation completed")
    })

    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
}
Exchange answered 10/3, 2015 at 8:12 Comment(6)
It's strange because I put this in my ViewController, and it didn't print anything to my log. I guess because this method is not being called. Can you think of anything else that would need to be plugged in order for this to work?Figured
I just added it to a empty project (Universal App) and it works fine without the need to add anything. Maybe put a log statement at the very beginning of the method and see if its being called. I cannot think of anything that you would need to add. What iOS you running?Exchange
@DogCoffee..its not getting called. Has it anything to do with Simulator?Exemplar
@Exemplar works in simulator as well - just checked again then. Works as expected.Exchange
is there a way to do this without subclassing UIVIewController, because we are doing MVVM-CCromagnon
statusbarorientation is deprecated in iOS 9. What else is the option?Higherup
A
10

iOS 10.3 & Swift 3

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {

        coordinator.animate(alongsideTransition: { (_) in
            let orient = newCollection.verticalSizeClass

            switch orient {
            case .compact:
                print("Lanscape")///Excluding iPads!!!

            default:
                print("Portrait")
            }
        }, completion: { _ in
            print("rotation completed")
        })

        super.willTransition(to: newCollection, with: coordinator)
    }
Ascites answered 11/4, 2017 at 12:0 Comment(2)
Why do you need animation? Can't you check 'newCollection' straight away?Bataan
@Bataan to sync animation with myAscites
S
7

The accepted answer in Swift 3:

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    coordinator.animate(alongsideTransition: { (_) in
        let orient = UIApplication.shared.statusBarOrientation

        switch orient {
        case .portrait:
            print("Portrait")
        // Do something
        default:
            print("Anything But Portrait")
            // Do something else
        }
    }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
      print("rotation completed")
    })

    super.willTransition(to: newCollection, with: coordinator)
}

It works fine for me 👍

Sensitize answered 18/11, 2016 at 16:34 Comment(2)
Doesn't work for me on iOS 10 — it prints the old orientation, not the new one.Willodeanwilloughby
@VaddadiKartick because you should use let orient = newCollection.verticalSizeClass switch orient { case .compact: print("Lanscape") // Do something default: print("Portrait") // Do something else }Ascites
M
5

Since the question was: what was the equivalent of didRotateFromInterfaceOrientation

I thought I'd contribute the code below:

@implementation ViewController
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    [super traitCollectionDidChange:previousTraitCollection];
    if (previousTraitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular) {
        NSLog(@"User has rotated to landscape");
    } else if (previousTraitCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact) {
        NSLog(@"User has rotated to portrait");
    }
}
@end

I was testing on an iPhone in the simulator, but my print statements won't get run if I test using the iPad since the traitsCollection won't change.

This is strange because this is exactly what Apple recommends:

- (void) traitCollectionDidChange: (UITraitCollection *) previousTraitCollection {
    [super traitCollectionDidChange: previousTraitCollection];
    if ((self.traitCollection.verticalSizeClass != previousTraitCollection.verticalSizeClass)
        || self.traitCollection.horizontalSizeClass != previousTraitCollection.horizontalSizeClass)) {
        // your custom implementation here
    }
}
Meta answered 27/1, 2016 at 21:9 Comment(4)
There is a missing bracket in the second code snippetLeffler
Does this works on iPad where both vertical and horizontal classes are Regular on full screen?Higherup
Your code is not the same as Apple's, you are only testing the vertical size class.Knight
It's been a while, looks like the content of the link has changed.Meta
S
3

[[UIApplication sharedApplication] statusBarOrientation] is deprecated in iOS9 you have to test against UITraitCollection for various devices.

  override func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    if newCollection.containsTraitsInCollection(UITraitCollection(verticalSizeClass: .Regular)) {
      ...
    }
  }
Send answered 19/10, 2015 at 12:50 Comment(2)
Only the setter was deprecated. An Apple employee posted, "Reading the status bar orientation is not deprecated, only writing to it is. This may have been an error in how we constructed the header if you are seeing this on the getter." (forums.developer.apple.com/thread/12937)Zoril
Isn't the getter also deprecated though. According to the documentation it is.Michal
U
1

On the Ipad there is no trait collection change so here is how you detect the rotation from start and completion. Here is the Swift 5 syntax:

override func viewWillTransition(to size: CGSize, with coordinator: 
UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    coordinator.animate(alongsideTransition: { [unowned self] _ in

        self.view.backgroundColor = UIColor.blue
        print("rotation in progress")

    }) { [unowned self] _ in
        self.view.backgroundColor = UIColor.green
        print("rotation complete")


    }
}
Undulant answered 4/12, 2019 at 14:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.