iOS 8旋转方法的弃用 - 向后兼容性

52

iOS 8中,界面旋转的方法已被弃用,包括:

  • willRotateToInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:
  • willAnimateRotationToInterfaceOrientation:duration:

替代方法包括:

  • willTransitionToTraitCollection:withTransitionCoordinator:
  • viewWillTransitionToSize:withTransitionCoordinator:

如果没有实现新的旋转方法,并使用iOS 8 SDK编译项目,则视图控制器将不会收到已弃用旋转方法的调用。

我的担心是:当使用iOS 7 SDK构建的应用程序已经在AppStore中,那么在iOS 8设备上是否仍会调用已弃用的旋转方法?

编辑:

旋转方法仍然会被调用,但在iOS 8中存在一些更改/问题/错误。

此外,UIScreen现在是面向接口的


1
它们会很好地运行;它们是使用iOS7 SDK构建的,当时这些方法还没有被弃用。不过,如果你用iOS8 SDK(一旦发布)编译项目,你需要关注并更新你的项目 - 但旧的应用程序将无需进一步操作仍然可以正常运行。 - holex
6个回答

36

我刚遇到了这个问题,想要暂时继续使用之前的方法,于是我这样做了。

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    //The device has already rotated, that's why this method is being called.
    UIInterfaceOrientation toOrientation   = [[UIDevice currentDevice] orientation];
    //fixes orientation mismatch (between UIDeviceOrientation and UIInterfaceOrientation)
    if (toOrientation == UIInterfaceOrientationLandscapeRight) toOrientation = UIInterfaceOrientationLandscapeLeft;
    else if (toOrientation == UIInterfaceOrientationLandscapeLeft) toOrientation = UIInterfaceOrientationLandscapeRight;

    UIInterfaceOrientation fromOrientation = [[UIApplication sharedApplication] statusBarOrientation];

    [self willRotateToInterfaceOrientation:toOrientation duration:0.0];
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        [self willAnimateRotationToInterfaceOrientation:toOrientation duration:[context transitionDuration]];
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        [self didRotateFromInterfaceOrientation:fromOrientation];
    }];

}

我还不确定是否应该在动画块以外使用它,因为我没有时长。

    [self willRotateToInterfaceOrientation:toOrientation duration:0.0];

需要注意的一点是UIDeviceOrientation与UIInterfaceOrientation不匹配,具体而言,UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight和UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft,因此你不能在viewWillTransitionToSize:withTransitionController:方法中混合使用它们。 - iain
此外,您还需要在其中某个地方调用 [super viewWillTransitionToSize:withTransitionController:]。 - iain
这是UIInterfaceOrientation的枚举类型定义:typedef NS_ENUM(NSInteger, UIInterfaceOrientation) { UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown, UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft };所以你说得对,我需要颠倒左右。 - Camo
很好的回答。讨厌viewWillTransitionToSize。但是有一个问题:willAnimateRotationToInterfaceOrientation在动画之前被调用(就像willRotateToInterfaceOrientation一样)-而不是像以前那样在动画期间被调用。 - Dmitry

19

iOS 8 SDK已经不再支持旋转方法。即使在iOS 8甚至未来几个版本的情况下,使用iOS 7 SDK构建的应用程序也不会受到影响。

例如,自iOS 3.0以来,UIButtonfont属性已被弃用,但仍可在iOS 7.0中使用。


3
@fabb请参考此处。“弃用(deprecation)”不意味着立即从框架或库中删除接口。而且,“弃用(deprecated)”API可能会在未来的操作系统版本中被删除。这就是所谓的弃用,它可能会从将来的操作系统版本中删除。 - mluisbrown
5
不知道谁没有给出理由就对这个回答进行了负评。这个答案是正确的,我们已经进行了测试。我们的一个企业应用支持iOS4.3版本,并且在iOS8 beta5上可以完美旋转。如果应用程序是使用iOS 8 SDK构建的,旋转回调将会引起麻烦。 - atastrophic
我遇到了一个与方向相关的新问题,当我从横屏旋转到竖屏时,UITableView单元格中的背景图像仍未更改。请问最好在哪里更改我的背景单元格图像? - wod
3
不要使用Xcode 6来构建您的应用程序,否则旋转功能将会失败。 - atastrophic
1
上面的评论是答案,无论您使用Xcode 6编译针对7.1或更低版本,您必须也使用Xcode 5或更改已弃用的方法。 - jigzat
显示剩余2条评论

6
您列出的已弃用的旋转方法仍会在运行于 iOS 8+ 设备上的应用程序中调用。如果您支持 iOS 7,则可以继续使用它们而没有问题。但是,如果您只支持 iOS 8+,最好使用非废弃的方法。
但是,请注意,如果您在同一视图控制器中实现了新的旋转方法和已弃用的旋转方法,则在 iOS 7 上运行时将调用已弃用的方法,在 iOS 8+ 上将仅调用代替已弃用的新方法。
例如,如果您只实现了 willRotateToInterfaceOrientation 方法,则在 iOS 7 和 8 上运行时都将调用此方法。如果您随后添加了 viewWillTransitionToSize 方法,则 iOS 7 仍将调用 willRotateToInterfaceOrientation,但 iOS 8 将不会调用它,而是仅调用 viewWillTransitionToSize

1
尽管您提到的所有设置都已经完成,但在iOS 8设备上didRotateFromInterfaceOrientation方法仍未被调用。 - Leon
@Leon didRotateFromInterfaceOrientation 在 iOS 8 12A365 上被调用,我刚刚在一个全新的 Swift 项目中尝试了一下。非常简单:新建一个单视图项目,在 ViewController 中重写 didRotateFromInterfaceOrientation 并添加 NSLog("rotated")。在 iPhone 和 iPad 的 iOS 7 和 8 上旋转完成后都会记录日志。实际上,即使您不将部署目标更改为 iOS 7,它也会被调用。 - Jordan H
这显然不止于此,我的NSLog没有显示。这可能是因为我的didRotateFromInterfaceOrientation方法在一个类别中而不是ViewController中吗? - Leon
@Leon 可能我从未尝试过。根据UIViewController类参考: “如果视图控制器在发生方向更改时不可见,则永远不会调用旋转方法。” - Jordan H
我不确定它如何适配。该方法在iOS 7设备上确实被调用,但在8上没有。我还有其他问题与该类别相关,这些问题只出现在8上,但没有任何弃用错误出现。非常奇怪,感觉更像是一个bug而不是其他什么。 - Leon
我发现即使在代码中没有willTransition方法,仍然会调用willRotate和didRotate。如果我添加willTransitionToTraitCollection和viewWillTransitionToSize,那么就不会调用willRotate和didRotate,但是如果我删除willTransition方法,则仍然会调用旧的方法。这是使用iOS 8.1基础SDK和8.0部署目标。 - BountyBob

2

我会检查这个特定的情况以确保百分之百的信心,但我不期望出现任何问题。我还建议您观看WWDC 2014216 Building Adaptive Apps with UIKit会话,以获取更多信息。看起来已弃用的方法没有被调用,因此应用程序应该更新以便在运行iOS 8的设备上正常工作。


3
实际上,我尝试使用iOS 8 SDK运行一个应用程序。已经不会调用已弃用的方法。 - fabb
1
只有在正确设置了部署目标的情况下,当应用程序在iOS 8设备上运行时,才会调用所提到的旋转方法。 - Jordan H
didRotateFromInterfaceOrientation对我也没有被调用。在7设备模拟器上运行的同一代码可以正常工作,但在8上却不能。 - Leon
2
由于似乎有一些混淆,不确定在iOS 8上是否调用了弃用的方法:对我来说,结果是它们确实被调用在根视图控制器上,但是它们不像在iOS 7上那样被调用在子视图控制器上。希望对你有所帮助。 - chris
如果您重写了viewWillTransitionToSize方法,那么didRotateFromInterfaceOrientation方法将不会被调用。 - JYC
显示剩余3条评论

1

1
对我而言,在这里我们通过一些计算和跟踪标题大小等内容的plist文件手动旋转“事物”(因此,如果我们想要更改按钮之类的东西,只需更改此plist而不是所有单独的xib)。并且我们所有的旋转代码都在willLayoutSubviews中,因此即使在新的iOS8上,所有的东西都是正确的...除了我也看到了对于新的iOS8 [[UIScreen mainScreen] bounds].size.width 现在根据设备方向而不是设备实际尺寸返回宽度。
我会将此帖子发布到其他线程:
- (BOOL) isIOS8OrAbove{
    float version802 = 1140.109985;
    float version8= 1139.100000; // there is no def like NSFoundationVersionNumber_iOS_7_1 for ios 8 yet?
    NSLog(@"la version actual es [%f]", NSFoundationVersionNumber);
    if (NSFoundationVersionNumber >= version8){
        return true;
    }
    return false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接