"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
}
我已经从 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
}