"interfaceOrientation" is deprecated in iOS 8、如何更改此方法 Objective C

"interfaceOrientation" is deprecated in iOS 8, How to change this method Objective C

我已经从 Cocoa 使用此方法的控件下载了一个 simpleCamera 视图

- (AVCaptureVideoOrientation)orientationForConnection
{
    AVCaptureVideoOrientation videoOrientation = AVCaptureVideoOrientationPortrait;
    switch (self.interfaceOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
            videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
            break;
        case UIInterfaceOrientationLandscapeRight:
            videoOrientation = AVCaptureVideoOrientationLandscapeRight;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            videoOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
            break;
        default:
            videoOrientation = AVCaptureVideoOrientationPortrait;
            break;
    }
    return videoOrientation;
}

问题是 "interfaceOrientation" 在 iOS 8 中已弃用,但我不知道在 Switch 条件下替换什么以及如何替换它。

获取设备方向不正确。例如,设备可能处于横向模式,但仅支持纵向的视图控制器将保持纵向。

改为使用:

[[UIApplication sharedApplication] statusBarOrientation]

另一个好处是它仍然使用 UIInterfaceOrientation 枚举,因此您的代码几乎不需要更改。

使用 -orientation 属性 的 UIDevice 是不正确的(即使它可以在大多数情况下工作)并且可能导致一些错误,例如 UIDeviceOrientation 还要考虑方向如果设备面朝上或朝下,UIInterfaceOrientation 枚举中没有这些值的对。
此外,如果您将应用程序锁定在某个特定方向,UIDevice 会在不考虑该方向的情况下为您提供设备方向。
另一方面,iOS8 弃用了 UIViewController class 上的 interfaceOrientation 属性。
有 2 个选项可用于检测界面方向:

  • 使用状态栏方向
  • 使用大小 classes,在 iPhone 如果它们没有被覆盖,它们可以让您了解当前的界面方向

仍然缺少一种理解界面方向变化方向的方法,这在动画中非常重要。
在 WWDC 2014 session "View controller advancement in iOS8"演讲者也提供了解决该问题的方法,使用替换 -will/DidRotateToInterfaceOrientation 的方法。

此处建议的解决方案已部分实施:

-(void) viewWillTransitionToSize:(CGSize)s withTransitionCoordinator:(UIVCTC)t {
    orientation = [self orientationFromTransform: [t targetTransform]]; 
    oldOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 
    [self myWillRotateToInterfaceOrientation:orientation duration: duration]; 
    [t animateAlongsideTransition:^(id <UIVCTCContext>) {
         [self myWillAnimateRotationToInterfaceOrientation:orientation
                                                  duration:duration];
      }
      completion: ^(id <UIVCTCContext>) {
         [self myDidAnimateFromInterfaceOrientation:oldOrientation];
      }];
}

自iOS8起,Apple 推荐使用 TraitCollections (Size 类) 而不是 interfaceOrientation。

此外,由于 iOS 9 和新的 iPad 功能 "Multitasking",在某些情况下设备方向不符合 window 比例! (破坏你的申请UI)

所以在使用Regular Size 类时你也应该非常小心,因为它不一定会占据整个iPad屏幕。

有时 TraitCollections 不能满足您的所有设计需求。对于这些情况,Apple 建议比较视图的边界:

if view.bounds.size.width > view.bounds.size.height {
    // ...
}

我很惊讶,但您可以查看 21'15 的 WWDC 2015 视频 Getting Started with Multitasking on iPad in iOS 9

也许您真正在寻找设备方向而不是屏幕或 window 比例。如果您关心设备相机,则不应使用 TraitCollection,也不应使用视图边界。

Swift 4+ 版本

UIApplication.shared.statusBarOrientation

当你使用UIApplication.shared.statusBarOrientation时,Xcode11会显示警告'statusBarOrientation' was deprecated in iOS 13.0: Use the interfaceOrientation property of the window scene instead.

此答案在Swift5中,支持iOS13及以下版本。它假设如下:

  • 您只会创建一个场景,绝不会超过一个
  • 您希望将您的代码包含在特定视图中
  • 您有一个视图,其成员变量 previewLayer 类型为 AVCaptureVideoPreviewLayer

首先,在您的 SceneDelegate.swift 中添加以下行:

    static var lastCreatedScene: UIWindowScene?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let newScene = (scene as? UIWindowScene) else { return }
        Self.lastCreatedScene = newScene
    }

然后在你的视图中,添加如下函数并在layoutSubviews()中调用:

    func refreshOrientation() {
        let videoOrientation: AVCaptureVideoOrientation
        let statusBarOrientation: UIInterfaceOrientation
        if #available(iOS 13, *) {
            statusBarOrientation = SceneDelegate.lastCreatedScene?.interfaceOrientation ?? .portrait
        } else {
            statusBarOrientation = UIApplication.shared.statusBarOrientation
        }
        switch statusBarOrientation {
        case .unknown:
            videoOrientation = .portrait
        case .portrait:
            videoOrientation = .portrait
        case .portraitUpsideDown:
            videoOrientation = .portraitUpsideDown
        case .landscapeLeft:
            videoOrientation = .landscapeLeft
        case .landscapeRight:
            videoOrientation = .landscapeRight
        @unknown default:
            videoOrientation = .portrait
        }
        self.previewLayer.connection?.videoOrientation = videoOrientation
    }